我已经学会了使用 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
多的命令。cp
find
使用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.