假设我有以下文件,布局如下:
$ tree
.
├── 01/
│ ├── example.txt
│ └── foobar.txt
├── 02/
│ └── example.txt
└── 03/
├── example.txt
└── test.txt
3 directories, 5 files
我想find .
按拓扑顺序(即目录名称在其内容之前)并在同一目录中按字母顺序打印目录和文件。相反,这些是我得到的结果:
$ find .
.
./02
./02/example.txt
./01
./01/foobar.txt
./01/example.txt
./03
./03/test.txt
./03/example.txt
我希望输出看起来像:
.
./01
./01/foobar.txt
./01/example.txt
./02
./02/example.txt
./03
./03/example.txt
./03/test.txt
我不想通过管道传输sort
到任何其他命令,因为我想在find
命令完成之前按顺序一一处理这些行。
答案1
你不能那样做。
如果要按特定顺序处理文件,则必须在开始处理之前按该顺序排列它们。
find
在文件系统中以任何顺序查找文件/目录(通常称为“目录顺序”,对于许多文件系统来说,它主要受创建日期的影响,但如果删除文件/目录,它们的位置可能会被重用,所以基本上你应该假设它是随机的),而在你的情况下,这似乎不是按字母顺序排列的。但按字母顺序排列在前,可能在文件系统中排在最后,因此,如果您想按字母顺序处理文件,则需要通读整个目录。
为了获得最接近您想要的结果,您可能需要进行一些编码。如果您扫描(搜索的)顶级目录,您知道接下来要扫描“01”目录,然后是“02”,...,在扫描“02”(以及后续目录)时,您可以开始处理“01”中的文件。 (如果您的目录结构更通用,请酌情进行概括。)
答案2
对于 GNU find
、sort
、 和xargs
:
find . -print0 | sort -z | xargs -0r process_the_files
process_the_files
是您将使用 find-exec
选项运行的任何程序或脚本。
这在整个管道中使用 NUL 作为文件名分隔符(-print0、-z 和 -0 选项),因此可以安全地使用包含任何有效字符(包括空格、制表符、换行符等)的文件名。
如果您想处理 find 生成的文件名列表(而不是这些文件的内容),您可以:
按原样使用上面的内容,并编写脚本
process_the_files
,以便它迭代文件名参数,而不是这些文件的内容。请注意process_the_files
,如果文件名列表太大而无法容纳在一个命令行中(这因操作系统而异,在 Linux 上约为 2MB),则 xargs 可能会运行多次。顺便说一句,
find ... -exec ... {} +
以同样的方式受到系统命令行长度的限制。跳过
xargs
管道的一部分,将排序的输出通过管道传递到您想要对它们执行的任何操作中 - 但那必须能够处理 NUL 分隔的输入(大多数 GNU 工具都可以,并且很容易用 awk 或 perl 编写自己的输入,甚至 sh - sh 变量不能包含 NUL,但这在您只使用时并不重要NUL 作为分隔符)。这样做不受命令行长度限制 - 它可以处理来自标准输入的任意数量的文件名。