在对另一个问题的回答中,我想使用类似这样的结构来查找出现在list2
但未出现在中的文件list1
:
( cd dir1 && find . -type f -print0 ) | sort -z > list1
( cd dir2 && find . -type f -print0 ) | sort -z > list2
comm -13 list1 list2
但是,我遇到了麻烦,因为我的版本comm
无法处理以 NULL 结尾的记录。(一些背景:我将一个计算列表传递给rm
,所以我特别希望能够处理可能包含嵌入式换行符的文件名。)
如果你想要一个简单的例子,试试这个
mkdir dir1 dir2
touch dir1/{a,b,c} dir2/{a,c,d}
( cd dir1 && find . -type f ) | sort > list1
( cd dir2 && find . -type f ) | sort > list2
comm -13 list1 list2
如果没有以 NULL 结尾的行,此处的输出是./d
仅出现在list2
.
我希望能够用来find ... -print0 | sort -z
生成列表。
我怎样才能最好地重新实现等效于输出出现在但未comm
出现在中的以 NULL 结尾的记录的等效项?list2
list1
GNU
comm
(从 GNU coreutils 8.25 开始)现在有一个-z
/--zero-terminated
选项。对于旧版本的 GNU
comm
,您应该能够交换 NUL 和 NL:这种方式
comm
仍然适用于以换行符分隔的记录,但输入中的实际换行符编码为 NUL,因此我们仍然可以安全地使用包含换行符的文件名。您可能还想将语言环境设置为,
C
因为至少在 GNU 系统和大多数 UTF-8 语言环境中,有不同的字符串排序相同,会在此处引起问题¹。这是一个非常常见的技巧(参见Invert matching lines, NUL-separated另一个例子
comm
),但是需要在输入中支持 NUL 的实用程序,这在 GNU 系统之外是相对罕见的。¹ 示例:
(2019 年编辑:①②③ 的相对顺序已在较新版本的 GNU libc 中得到修复,但您可以使用 ? ? ? 代替,例如在较新版本(至少 2.30)中仍然存在 95% 的 Unicode 代码点等问题)