如何按字母顺序和拓扑顺序对“find”的结果进行排序?

如何按字母顺序和拓扑顺序对“find”的结果进行排序?

假设我有以下文件,布局如下:

$ 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 findsort、 和xargs

find . -print0 | sort -z | xargs -0r process_the_files

process_the_files是您将使用 find-exec选项运行的任何程序或脚本。

这在整个管道中使用 NUL 作为文件名分隔符(-print0、-z 和 -0 选项),因此可以安全地使用包含任何有效字符(包括空格、制表符、换行符等)的文件名。

如果您想处理 find 生成的文件名列表(而不是这些文件的内容),您可以:

  1. 按原样使用上面的内容,并编写脚本process_the_files,以便它迭代文件名参数,而不是这些文件的内容。请注意process_the_files,如果文件名列表太大而无法容纳在一个命令行中(这因操作系统而异,在 Linux 上约为 2MB),则 xargs 可能会运行多次。

    顺便说一句,find ... -exec ... {} +以同样的方式受到系统命令行长度的限制。

  2. 跳过xargs管道的一部分,将排序的输出通过管道传递到您想要对它们执行的任何操作中 - 但那必须能够处理 NUL 分隔的输入(大多数 GNU 工具都可以,并且很容易用 awk 或 perl 编写自己的输入,甚至 sh - sh 变量不能包含 NUL,但这在您只使用时并不重要NUL 作为分隔符)。这样做不受命令行长度限制 - 它可以处理来自标准输入的任意数量的文件名。

相关内容