13

我有一个基于在 bash 中运行“查找”命令的结果的目录列表。例如, find 的结果是文件:

test/a/file
test/b/file
test/file
test/z/file

我想对输出进行排序,使其显示为:

test/file
test/a/file
test/b/file
test/z/file

有没有办法在 find 命令中对结果进行排序,或者通过管道将结果进行排序?

4

4 回答 4

21

如果你有 GNU 版本的 find,试试这个:

find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}'

要在循环中使用这些文件名,请执行

find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}' | while read file; do
    # use $file
done

find 命令为每个文件打印三件事:(1)它的目录,(2)它在目录树中的深度,以及(3)它的全名。通过在输出中包含深度,我们可以使用上面sort -n的排序。最后,我们使用删除前两列,因为它们仅用于排序。test/filetest/a/fileawk

用作\0三个字段之间的分隔符允许我们处理其中包含空格和制表符的文件名(但不幸的是,不是换行符)。

$ find test -type f
test/b/file
test/a/file
test/file
test/z/file
$ find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F'\0' '{print $3}'
test/file
test/a/file
test/b/file
test/z/file

如果您无法修改find命令,请尝试以下复杂的替换:

find test -type f | while read file; do
    printf '%s\0%s\0%s\n' "${file%/*}" "$(tr -dc / <<< "$file")" "$file"
done | sort -t '\0' | awk -F'\0' '{print $3}'

它做同样的事情,${file%/*}用于获取文件的目录名称和tr用于计算斜杠数量的命令,这相当于文件的“深度”。

(我当然希望那里有一个更简单的答案。你所问的似乎并不难,但我正在空白一个简单的解决方案。)

于 2013-01-23T23:12:28.747 回答
1
find test -type f -printf '%h\0%p\n' | sort | awk -F'\0' '{print $2}'

结果find是,例如,

test/a'\0'test/a/file
test'\0'test/file
test/z'\0'test/z/file
test/b'\0'test/b/text file.txt
test/b'\0'test/b/file

其中'\0'代表空字符。

这些复合字符串可以用一个简单的正确排序sort

test'\0'test/file
test/a'\0'test/a/file
test/b'\0'test/b/file
test/b'\0'test/b/text file.txt
test/z'\0'test/z/file

最后的结果是

test/file
test/a/file
test/b/file
test/b/text file.txt
test/z/file

(根据 John Kugelman 的回答,删除了“深度”元素,这绝对是多余的。)

于 2021-03-20T19:11:57.400 回答
0

尝试这个。作为参考,它首先对第二个字段第二个字符进行排序。它仅存在于文件中,并且具有 ar 的反向含义,它是第一个,之后它将对第二个字段的第一个字符进行排序。[-t 是字段分隔符,-k 是关键]

find test -name file |sort -t'/' -k2.2r -k2.1

做一个info sort了解更多信息。有很多不同的方法可以一起使用 -t 和 -k 来获得不同的结果。

于 2013-01-23T23:19:13.403 回答
0

如果要按字母顺序排序,最好的方法是:

find test -print0 | sort -z

(原始问题中的示例实际上想要目录之前的文件,这不一样,需要额外的步骤)

于 2019-06-09T23:25:23.077 回答