从所有子目录中复制特定扩展名的所有文件

194

在Unix下,我想将所有具有特定扩展名(例如所有的Excel文件)的文件从所有子目录复制到另一个目录。我有以下命令:

在Unix系统下,我希望可以使用以下命令将所有特定扩展名的文件(例如Excel文件)从所有子目录复制到另一个目录:

cp --parents `find -name \*.xls*` /target_directory/

这个命令存在以下问题:

  • 它也会复制目录结构,而我只想要文件(所有文件应该最终都在 /target_directory/ 中)

  • 它不会复制文件名中带有空格的文件(而这样的文件还是相当多的)

对于这些问题有什么解决方案吗?


find... exec mv 怎么样? - fedorqui
可能是根据扩展名将文件移动到目录中的重复问题。 - jww
1
这个问题实际上回答了我来这里提问的问题。谢谢! - ingernet
7个回答

288

--parents是复制目录结构,所以你应该把它去掉。

按照你的写法,find 命令执行后,输出被放置在命令行上,导致 cp 无法区分文件名之间的空格和文件名内部的空格。最好的做法是这样:

$ find . -name \*.xls -exec cp {} newDir \;

对于find找到的每个文件名,执行cp并将文件名正确传递。有关此技术的更多信息,请点击这里

除了以上所有内容,您还可以使用zsh,并简单地键入:

$ cp **/*.xls target_directory

zsh 可以扩展通配符来包括子目录,使这种操作变得非常容易。


2
是的,“bin it”意味着把它扔掉。现在已经修正了 :-) - Brian Agnew
18
Bash 4.0+和ksh93也支持**。对于bash,使用shopt -s globstar来启用它。对于ksh,可以使用set -Gset -o globstar - pynexj
6
这个执行程序在技术上比传递给xargs不够高效,因为xargs将以尽可能少的cp调用完成所有操作:find . -name '*.xls' -print0 | xargs -0 cp -t destdir - Taywee
2
@Taywee - 是的。然而,我不想让事情变得混乱,只是专注于特定问题。进一步提高效率措施总是好的。 - Brian Agnew
2
@BrianAgnew 噢,我相信,只是对于那些搜索错误的谷歌用户来说,在注释中获得额外信息还是很好的。 - Taywee
显示剩余7条评论

57

基于以上所有内容,我得出了这个版本。 这个版本在Mac恢复终端中也适用。

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'
它将在当前目录以及所有子目录中递归查找扩展名为xsl的文件,并将它们全部复制到目标目录。

cp标志如下:
  • p - 保留文件属性
  • r - 递归操作
  • v - 显示被复制的文件信息

1
这与我在SSH登录Bluehost时所做的相同。 - Plummer
10
不保留子目录。 - b005t3r
6
@b005t3r这是有意设计的,本来就不应该这样。这正是原帖提问者的初衷。他想要将所有子目录中的文件复制到一个没有子目录的目录中。 - Madivad
3
有没有一种方法可以修改它以保留子目录? - Matthew Dean
4
@MatthewDean 你可以使用--parents标志来实现cp的操作。类似这样的命令:find ./ -name '*.xsl' -exec cp --parents {} targetDir/ ';' - drmercer
大括号的作用是什么?为什么要使用分号“;”? - Jordan McBain

12

我遇到了类似的问题。我使用以下方法解决:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

'{}'";" 会在每个文件上执行复制操作。


7

在2022年,zsh解决方案也适用于Linux Bash:

cp **/*.extension /dest/dir

正常运作。

1
它不会创建子文件夹。 - undefined

6

我也曾经需要做这件事。我是通过使用cp命令的--parents参数来完成的:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;

2
find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

你可以删除"--parents",但如果多个文件具有相同的名称,则存在碰撞风险。原始答案翻译为:"最初的回答"。

0
在macOS Ventura 13.1上,使用zsh时,当需要复制的文件过多时,我看到了以下错误信息:
zsh: argument list too long: cp

我不得不使用find命令和cp命令一起将文件复制到我的目标位置:

find ./module/*/src -name \*.java -print | while read filelocation; do cp $filelocation mydestinationlocation; done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接