为什么我无法将 find 结果通过管道传输到 cp 中,但使用 exec 却可以工作?

plo*_*man 2 bash exec find

我用来find列出多个目录中具有特定扩展名的文件。我试过

find /path/to/encompassing/directory/ -d -name "*modified.tif" | xargs  cp Destination_Directory/ 
Run Code Online (Sandbox Code Playgroud)

但没有成功。使用

find /path/ -d -name "*modified.tif" -type f -exec cp {} Destination_Directory \;
Run Code Online (Sandbox Code Playgroud)

有效,但我不明白为什么 xargs 不起作用。

Ben*_* W. 6

如果你写

find -name '*modified.tif' | xargs cp directory
Run Code Online (Sandbox Code Playgroud)

那么这和写作是一样的

cp directory file1modified.tif file2modified.tif
Run Code Online (Sandbox Code Playgroud)

(或任何匹配的文件名),这是错误的方法,因为xargs默认情况下会附加参数。

find -name '*modified.tif' -exec cp {} directory \;
Run Code Online (Sandbox Code Playgroud)

是相同的

cp file1modified.tif directory
cp file2modified.tif directory
Run Code Online (Sandbox Code Playgroud)

这就是你想要的。

xargs您可以通过使用来实现相同的目的

xargs -I{} cp {} directory
Run Code Online (Sandbox Code Playgroud)

指定要在命令中使用参数的位置,但这意味着一次只会复制一个文件(因为-I暗示-L1)。

为了避免cp每个文件调用一次,您可以使用-t选项 for cp,以便将要复制的文件附加到命令的末尾(需要 GNU cp):

find -name '*modified.tif' | xargs cp -t directory
Run Code Online (Sandbox Code Playgroud)

这相当于

cp -t directory file1modified.tif file2modified.tif
Run Code Online (Sandbox Code Playgroud)

或者更好,处理文件名中的空格,

find -name '*modified.tif' -print0 | xargs -0 cp -t directory
Run Code Online (Sandbox Code Playgroud)

或者,没有xargs

find -name '*modified.tif' -exec cp -t directory {} +
Run Code Online (Sandbox Code Playgroud)

where-exec {} +确保调用cp次数尽可能少。