如何在单个目录中查找子目录中的文件并按文件名对它们进行排序?


9

使用进行正常查找的结果find . ! -path "./build*" -name "*.txt"

./tool/001-sub.txt
./tool/000-main.txt
./zo/001-int.txt
./zo/id/002-and.txt
./as/002-mod.txt

以及何时排序sort -n

./as/002-mod.txt
./tool/000-main.txt
./tool/001-sub.txt
./zo/001-int.txt
./zo/id/002-and.txt

但是所需的输出是:

./tool/000-main.txt
./zo/001-int.txt
./tool/001-sub.txt
./zo/id/002-and.txt
./as/002-mod.txt

这意味着输出仅基于文件名排序,但是文件夹信息应作为输出的一部分进行维护。

编辑:使示例更加复杂,因为子目录结构可能包含多个层次。


2
看到这个问题我问的SO:stackoverflow.com/questions/3222810/...
CAMH

@camh-如果可能的话,我只想使用Unix命令。无论如何,我的问题几乎是你的问题。您是否可以将最佳解决方案转移到该线程(始终保持与原始线程的链接),以便我将其标记为解决方案?
8:51解开

如果@Shawn做出了我在注释中建议的更改(使用-printf代替awk),我认为这是最好的解决方案。我已经对原始实现进行了重新设计以使用此方法。
卡姆(Camh)2011年

Answers:


9

您需要按最后一个字段排序(考虑/为字段分隔符)。不幸的是,我想不出一个可以在字段数变化时执行此操作的工具(如果只能sort -k取负值)。

为了解决这个问题,您必须做一个decorate-sort-unecorate。也就是说,将文件名放在开头,然后是字段分隔符,然后进行排序,然后删除第一列和字段分隔符。

find . ! -path "./build*" -name "*.txt" |\
    awk -vFS=/ -vOFS=/ '{ print $NF,$0 }' |\
    sort -n -t / |\
    cut -f2- -d/

awk命令说字段分隔符 FS设置为/; 这会影响它读取字段的方式。在输出字段分隔符 OFS也被设置为/; 这会影响其打印记录的方式。下一条语句表示打印最后一列(NF是记录中的字段数,因此它也恰好是最后一个字段的索引)以及整个记录($0是整个记录);它将打印它们之间的OFS。然后sort编辑列表,将其/视为字段分隔符-由于我们在记录中首先拥有文件名,因此它将以此排序。然后cut仅打印到最后的字段2,再次将其/视为字段分隔符。


3
由于这是与find(1)一起使用的,因此您可以跳过awk部分并使用-printf '%f/%p\n'
camh 2011年

确实,我们的设置稍微复杂一些。它确实包括可变的子目录深度。编辑了问题以反映这一事实。抱歉,我一开始没有将其包括在内。
取消播放

1
@Unode:Shawn的解决方案可以很好地处理可变深度,这是解决此问题的规范方法(最多可以有微小的变化)。
吉尔(Gilles)'所以

4

我将使用文件'-printf'输出名称和路径,按名称排序,并在最后一步中切断名称。“ ###”只是一个标记,有助于剪切。

find -name "*.txt" -printf "%f###%p\n" | sort -n | sed 's/.*###//'

%f显示文件名,%p显示整个路径。

我简化了find-command使其成为一行,当然您将离开此! -path "./build*"部分。


3

在zsh≥4.3.10中:

print -l -- **/*.txt~build*(oe\''REPLY=${REPLY:t}'\')
  • **/*.txt递归匹配*.txt当前目录及其子目录。
  • ~build* 排除文本以build*(例如! -path './build*')开头的匹配项。(您需要setopt extended_glob首先。)
  • (oe\''…'\')是排序glob限定词REPLY=…从返回的字符串构造要排序的字符串。
  • ${REPLY:t}是路径的基础名称(“ tail”)。

很多级联的魔术。有趣,但是我们仅限于sh语法。+1
取消播放
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.