我想find
一些文件,并使用管道命令计算shasum
。
find . -type f | xargs shasum
但是我的目录中有文件带引号,例如名为
的文件file with "special" characters.txt
管道输出如下所示:
user@home ~ $ find . -type f | xargs shasum
da39a3ee5e6b4b0d3255bfef95601890afd80709 ./empty1.txt
da39a3ee5e6b4b0d3255bfef95601890afd80709 ./empty2.txt
da39a3ee5e6b4b0d3255bfef95601890afd80709 ./empty3.txt
shasum: ./file:
shasum: with: No such file or directory
shasum: special: No such file or directory
shasum: characters.txt: No such file or directory
25ea78ccd362e1903c4a10201092edeb83912d78 ./file1.txt
25ea78ccd362e1903c4a10201092edeb83912d78 ./file2.txt
文件名中的引号会产生问题。
如何告诉shasum
正确处理文件?
答案 0 :(得分:5)
简短的解释是,xargs
被广泛认为是按设计划分的,除非使用标准的扩展来禁用其尝试解析和兑现引用和转义内容的行为它的输入。有关详细信息,请参阅the xargs
section of UsingFind。
在具有GNU或现代BSD扩展(包括MacOS X)的系统上,您可以(并且应该)NUL分隔find
的输出:
find . -type f -print0 | xargs -0 shasum --
find -exec
也就是说,你可以通过完全符合现代(~2006)POSIX的方式将xargs
完全取出来做得更好:
find . -type f -exec shasum -- '{}' +
请注意,--
参数指定shasum
以后所有参数都是文件名。如果您使用find * -type f ...
,那么您可以使用短划线开始结果;使用--
可确保此结果不会被解释为一组选项。
如果您有GNU xargs,但不要可以选择NUL分隔的输入流,那么xargs -d $'\n'
(在shell中,例如带有ksh扩展名的bash)将会避免引用和转义行为:
xargs -d $'\n' shasum -- <files.txt
然而,这不是最理想的,因为换行文字实际上可能在文件名中,因此无法区分分隔两个名称的换行符和作为实际名称一部分的换行符。请考虑以下情形:
mkdir -p ./file.txt$'\n'/etc/passwd$'\n'/
touch ./file.txt$'\n'/etc/passwd$'\n'file.txt file.txt
find . -type f | xargs -d $'\n' shasum --
这将具有类似于以下内容的输出:
da39a3ee5e6b4b0d3255bfef95601890afd80709 ./file.txt
da39a3ee5e6b4b0d3255bfef95601890afd80709 ./file.txt
c0c71bac843a3ec7233e99e123888beb6da8fbcf /etc/passwd
da39a3ee5e6b4b0d3255bfef95601890afd80709 file.txt
...因此允许可以控制文件名的攻击者为任意文件外部导致shasum将目标结构添加到您的输出中。