如何使用gnu cp命令将文件复制到多个目录?

219

使用cp命令复制单个文件到多个目录是否可能?

我尝试了以下命令,但都没有成功:

cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}

我知道可以使用for循环或者find命令实现,但是是否可以使用GNU的cp命令来实现?

22个回答

602

你不能仅使用 cp 来完成此操作,但你可以将 cpxargs 结合使用:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

file1复制到dir1dir2dir3。使用xargs调用cp 3次完成此操作,请参阅xargs的man页面获取详细信息。


3
xargs 的更多信息:http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/ - Chris Bier
24
@Simon 怎么了?“你不能仅仅使用cp命令来完成这个任务。”仅仅因为答案试图通过提供另一种方法来帮助你,并不意味着问题没有得到回答。 - Nicole
3
问者指定了: “我知道可以使用for循环或find实现,但是否可以使用gnu cp命令实现?” 被接受的答案是正确的答案。 - Simon
27
规定答案是否符合技术要求来确定其是否回答问题是无法忍受的学究气息,也不是很有用。 - Backgammon
4
非常有帮助!对于像我这样的初学者来说:你不能在cp命令中使用正则表达式,但是你可以在该命令的第一部分中使用正则表达式(例如 echo dir[1-3] | xargs -n 1 cp filename)。 - Jason
显示剩余7条评论

113

不,cp可以复制多个源文件,但只能复制到单个目标文件。如果你想要实现你所需的功能,你需要安排多次调用cp,每次对应一个目标文件,使用循环或其他工具,就像你说的那样。


谢谢你的回答!现在我再想一想,如果没有额外的标志(这些标志不存在),cp 命令将不知道哪个是源目录,哪个是目标目录。 - Tom Feiner
10
这不是正确的答案。请查看Robert Gamble的答案。 - Debajit
26
@Nocturne:我所说的哪一部分是不正确的?Robert给出了使用另一个工具来多次调用cp的示例,正如我所建议的那样。有许多可能的解决方案涉及使用其他工具或构造来实现这一点,但是OP确实指出他已经知道这是可能的。 - moonshadow
2
很遗憾,如果cp(和scp)支持该功能将会非常好。但是我们可以使用tee来进行分割。http://superuser.com/questions/32630/parallel-file-copy-from-single-source-to-multiple-targets - Simon
4
当然,你的答案是正确的。我认为PlagueHammer想要表达的是在这种情况下另一个答案更有用。也许你可以在你的回答中加入类似的内容? - Peaceful

79

通配符也适用于Roberts的代码

echo ./fs*/* | xargs -n 1 cp test 

例如,要将位于我的桌面上的根所有权文件(实际上是符号链接)移动到所有用户的桌面上,我首先必须sudo su(否则无法工作),然后使用:echo /home/*/Desktop/ | xargs -n 1 cp -av /home/myusername/Desktop/file。 - David G
macOS 11 Big Sur:运行良好!我用它快速传播Finder文件夹视图设置,这些设置存储在一个.DS_Store文件中,从我的源文件夹到所有兄弟文件夹。echo ../* | xargs -n 1 cp .DS_Store 运行良好。幸运的是,除了自己以外,所有目标都被复制了。 cp: ../my-current-folder/.DS_Store and .DS_Store are identical (not copied).'在第一次测试运行中,我使用了 test.txt,然后轻松批量删除了 rm ../*/test.txt。复制.DS_Store文件也成功了。P.S.:不幸的是,Finder文件夹视图定制没有传播。但这是另一个问题。 - porg

20

1
我刚进行了一个简略的测试,结果表明如果你需要将文件拷贝到不同的物理驱动器上(例如为数字影片源视频保留两个物理副本),这是最佳的性能表现。 - curiouser
1
如果您使用的是bash 3.0或更高版本,则可以使用以下范围:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null - Samuel
tee < inputfile outfile1 outfile2 > /dev/null 这个模式也是非常有用的,正如 Taywee 的回答所示。请注意使用 '<' 进行 io 重定向,这样就不需要从 cat 进行管道传输了。 - Alex Telon

19

据我所见,您可以使用以下内容:

ls | xargs -n 1 cp -i file.dat

cp 命令的 -i 选项表示当你要将 file.dat 文件复制到当前目录下时,它会询问你是否要覆盖该目录下的同名文件。虽然这不是完全自动化的解决方案,但对我有用。


1
虽然添加了-i保护是好的,但这不会提示您覆盖每个文件吗?而不是复制到目录中? - Hedgehog
1
@Hedgehog 嗯,我认为当目录中有一个文件并且想要将其复制到目录的子目录中时,这个命令非常有用。在这种情况下,文件只能被覆盖一次。感谢您的提问! - Evgeny
2
对我来说,它打印了一系列cp: overwrite问题,但我不需要回答任何一个问题,它也没有覆盖文件。 - Evgeni Sergeev
还打印了一系列问题+复制到以dir名称结尾的文件中,没有任何可行的解决方案,Paul的解决方案完美运行。 - eleuteron

12

这些答案都比明显的答案更加复杂:

for i in /foo /bar; do cp "$file1" "$i"; done

1
一个优雅且可行的方法是,要对当前目录中的所有目录执行此操作,可以使用for d in */ ; do cp $file "$i" done - FantomX1
1
@FantomX1 我认为你打错了。应该是:for i in */ ; do cp $file "$i" done?但还是谢谢你们两个。 - Torsten
@Torsten 是的,我测试过了,正如你所说,我有一个错别字,感谢你的纠正。 - FantomX1

9

ls -db di*/subdir | xargs -n 1 cp File

-b 的作用是在目录名中有空格时,避免被xargs误认为不同的项,因为这种情况下echo版本会存在问题。


7

并非直接使用cp命令,而是...

这是我在将大量Gopro录像从(缓慢的)SD卡复制到三个(缓慢的)USB驱动器时遇到的问题。我只想读取数据一次,因为它需要很长时间。我还想递归地进行操作。

$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )

(如果您需要更多输出,可以添加更多这样的>()部分。)我没有对此进行基准测试,但它绝对比循环中的cp(或一堆并行cp调用)要快得多。

5

如果在 Mac OS 上使用 xargs 复制文件到带有通配符的目录中,而且该目录名称中包含空格,那么唯一适用于我的解决方案是:

find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test 

其中test是要复制的文件,./fs*/*是要复制到的目录。

问题在于xargs将空格视为新参数,使用-d-E更改分隔符字符的解决方案在Mac OS上不起作用。


5
如果你想不使用分叉命令完成这件事:

tee <inputfile file2 file3 file4 ... >/dev/null

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