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

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

使用正常查找的结果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

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

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

答案1

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

为了解决这个问题,你必须进行装饰-排序-取消装饰。也就是说,获取文件名并将其放在开头,后跟字段分隔符,然后进行排序,然后删除第一列和字段分隔符。

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 到末尾,再次将其/视为字段分隔符。

答案2

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

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

%f 打印文件名,%p 打印整个路径。

我简化了 find-命令,使其成为一行,当然你会留下这一! -path "./build*"部分。

答案3

在 zsh ≥4.3.10 中:

print -l -- **/*.txt~build*(oe\''REPLY=${REPLY:t}'\')
  • **/*.txt匹配*.txt当前目录及其子目录递归地
  • ~build* 排除匹配其文本以build*(like ! -path './build*') 开头的内容。 (你setopt extended_glob首先需要。)
  • (oe\''…'\')是一个排序全局限定符REPLY=…从要返回的字符串构造要排序的字符串。
  • ${REPLY:t}是个基本名称路径的(“尾部”)。

相关内容