为什么“find / -name '*.txt' | cp /junk”不起作用?

为什么“find / -name '*.txt' | cp /junk”不起作用?

如果我想查找名称中包含 .txt 的任何文件,并且对于找到的每个匹配项,将其复制到 /junk 文件夹中,则可以考虑使用以下方法;

find / -name "*.txt" | cp /junk

但这是行不通的,因为 find 将以列表形式生成结果,而该列表无法输入 cp 中。

所以我可以使用 xargs 来解决这个问题

find / -name "*.txt" | xargs cp /junk

因为 xargs 会将列表更改为一行,可以将其输入 cp 中。我还认为这个命令将完全完成对文件的搜索,“生成列表”,然后它才会运行管道的右侧(副本)。

或者(最好)我可以使用 exec

find / -name ".txt" -exec cp {} /junk \;

每次找到匹配项时都会运行副本(并且会在单独的进程中运行副本,因此 find 命令将继续并行运行)。

有人可以确认这些命令和我的理解是正确的吗?

我应该补充一点,这仅用于教育目的,这不是现实生活场景。

答案1

  1. 是的,find / -name "*.txt" | cp /junk不会工作,因为cp不从标准输入读取其参数。
  2. 不,find / -name "*.txt" | xargs cp /junk也不起作用,因为xargs将从 stdin 读取的参数附加到命令中,因此cp会尝试以错误的方向复制。 (您可以尝试使用选项-I来修复该问题xargs,但随后您可以简单地使用find -exec。)
  3. 是的,find / -name ".txt" -exec cp {} /junk \;可以工作,但将为每个文件使用一次调用cp(并且一旦找到文件就会启动该命令)。

您也可以尝试这个解决方案,我应该只启动一次调用cp(或者至少会启动尽可能少的调用,命令行长度有限):

find / -path /junk -prune -or -name '*.txt' -print0 | xargs -0 sh -c 'cp "$@" /junk'

cp -t正如 @don_chrissti 评论的,如果你有 GNU cp,你就可以使用。然后可以这样做

find / -path /junk -prune -or -name '*.txt' -print0 | xargs -0 cp -t /junk

甚至

find / -path /junk -prune -or -name '*.txt' -exec cp -t /junk {} +

所有这三个都将收集命令行上尽可能多的参数并执行尽可能少的实例cp。但仍然可能出现 a 在完成cp之前启动的情况find,因此我们必须排除/junk,否则它可能会找到副本。

相关内容