将 find 与其他命令结合起来:何时使用 -exec 以及何时使用管道?

将 find 与其他命令结合起来:何时使用 -exec 以及何时使用管道?

我已经学会了使用 find 命令本身来查找文件和目录,但是当涉及到对文件/文件夹执行某些操作时,我感到很困惑。

给出以下命令:

find . -type f -iname "*.cr2" 

如果我想将上面找到的这些文件复制到新目录,我自然会想到使用 copy( cp) 和 pipeline |

find . -type f -iname "*.cr2" | cp \destination_directory

对我来说,这会将我的所有照片放在整个驱动器上,并将子文件夹级别嵌套到一个文件夹中,准备开始组织。

然而人们一直告诉我使用参数-exec,所以我的问题是你如何知道何时使用管道|以及何时使用-exec如下命令?

 find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;

编辑

建议的解决方案(如下)仅复制文件名唯一的文件。它说 cp 不会复制 file.txt 并替换为 file.txt。如果您复制了很多文件,并且不知道是否会有同名文件,那么如何复制某些文件并在文件名存在的情况下重命名它?

建议的解决方案

find . -type f -iname "*.txt" -print0 | xargs -0 cp -t /home/josh/Documents/copy/

/home/josh/documents/copy 是我想要将内容移动到的目录。

答案1

您的假设存在错误,但首先是一些背景:

您应该辨别 的两种用途-exec

  • 将 被替换为找到的单个\;项目{}
  • 将被许多+项目{}替换(命令行可以容纳的数量)。

因此,您的使用示例会调用与 找到的项目一样-exec多的命令。cpfind

使用find ... -exec cmd {} ... +效率与将 find 的输出通过管道传输到处理多个输入名称的命令中类似。

您还应该考虑到可以-exec很好地处理带空格的文件名/路径,但是当您将 find 的输出通过管道传输到另一个程序时,可能会导致问题。因此,某些需要来自 stdin 的文件名列表的程序可以选择将这些文件名用 NUL 分隔(通常-0是 或--null)。并且find可以选择通过指定以下方式将它们提供给下一个程序:-print0


现在来看你的例子:

find . -type f -iname "*.cr2" | cp destination_directory

不复制找到的文件,因为 cp 不从标准输入读取。你必须使用:

find . -type f -iname "*.cr2" | xargs cp -t destination_directory

或处理带空格的路径:

find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory

您可以以大约相同的效率执行以下操作:

find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +

(正如 G-Man 指出的{}必须位于末尾、之前+)以上所有内容均适用不是为此在目标目录下构建层次结构,并且出于长期习惯,即使源目录是平坦的,我发现自己使用cpio

find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory

它很好地列出了它一路上所做的事情。


相关部分来自man find

-exec command ;
       Execute command; true if 0 status is returned.   All  following
       arguments  to  find  are  taken  to be arguments to the command
       until an argument consisting of `;' is encountered.  The string
       `{}'  is  replaced  by  the  current  file name being processed
       everywhere it occurs in the arguments to the command, not  just
       in  arguments  where  it is alone, as in some versions of find.
       Both of these constructions might need to be  escaped  (with  a
       `\')  or  quoted  to  protect them from expansion by the shell.
       See the EXAMPLES section for examples of the use of  the  -exec
       option.   The  specified  command  is run once for each matched
       file.  The command  is  executed  in  the  starting  directory.
       There  are unavoidable security problems surrounding use of the
       -exec action; you should use the -execdir option instead.

-exec command {} +
       This variant of the -exec action runs the specified command  on
       the  selected files, but the command line is built by appending
       each selected file name at the end; the total number of invoca‐
       tions  of  the  command  will  be  much less than the number of
       matched files.  The command line is built in much the same  way
       that xargs builds its command lines.  Only one instance of `{}'
       is allowed within the command.  The command is executed in  the
       starting directory.

相关内容