在 Mac 上使用 GNU 工具
我不确定发生了什么,但似乎将 find 的输出通过管道传输到 xargs 时,在接触出现在不同位置的目录结构中的同名文件时存在一些问题
我的目录:
dir
-- dirone
---- myfile.txt
---- otherfile.txt
-- dirtwo
---- myfile.txt
当我运行此命令时,出现权限被拒绝错误:
find dir -name "myfile.txt" | xargs -0 -I FILE sh -c "ls FILE"
我什至无法触摸/ls 文件。如果我访问其中有一个“otherfile.txt”,我看不到任何问题
find dir -name "otherfile.txt" | xargs -0 -I FILE sh -c "ls FILE"
是否存在某种竞争条件或其他什么?我最终想修改这些文件,sed -i
但我什至无法 ls 它们。我不明白,因为完整的文件路径正在传递给 xargs,所以它应该具有完整的路径,使得它的相同名称并不重要,对吗?
编辑:好的,仍然不明白为什么我收到权限错误,但这似乎有效:
find dir -name "otherfile.txt" -type file -print0 | xargs -0 -I FILE sh -c "ls FILE"
只是删除-0
也有效,我不确定哪种方法更好/更安全?
答案1
鉴于您的目录设置:
$ find dir
dir
dir/dirtwo
dir/dirtwo/myfile.txt
dir/dirone
dir/dirone/myfile.txt
dir/dirone/otherfile.txt
如果我使用您的(原始)命令,那么我可以重现您的原始问题:
$ find dir -name "myfile.txt" | xargs -0 -I FILE sh -c "ls FILE"
dir/dirtwo/myfile.txt
sh: line 1: dir/dirone/myfile.txt: Permission denied
$
为了更好地理解发生了什么,让我们尝试一下该命令的变体:
$ find dir -name "myfile.txt" | xargs -0 -I FILE echo -FILE-
-dir/dirtwo/myfile.txt
dir/dirone/myfile.txt
-
请注意,FILE 扩展为单身的令牌:dir/dirtwo/myfile.txt\ndir/dirone/myfile.txt\n
.为什么?因为您告诉xargs
标记是 NUL 分隔的(使用-0
开关),并且两个文件名之间没有 NUL 字符。
这样,如果我们回到原来的命令:... | xargs -0 -I FILE sh -c "ls FILE"
,就会变成:
ls dir/dirtwo/myfile.txt
dir/dirone/myfile.txt
因此它列出了一个,并尝试运行第二个。这就是为什么你会收到“权限被拒绝”的信息——第二个文件不可执行。
正如您所发现的,添加选项-print0
即可find
解决问题。使用该选项,find
将在标记之间放置一个 NUL 字符——xargs
与使用该-0
选项时期望的字符相同。同样,只需关闭-0
选项即可xargs
解决问题,因为默认情况下find
和都xargs
使用空格作为分隔符。
-print0
和选项-0
对于文件名可以包含空格的情况很有用(这会破坏空格被视为标记分隔符的默认行为)。