当管道 find 到 xargs 时,无法修改位于不同位置的同名文件

当管道 find 到 xargs 时,无法修改位于不同位置的同名文件

在 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对于文件名可以包含空格的情况很有用(这会破坏空格被视为标记分隔符的默认行为)。

相关内容