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


210

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

我尝试了以下方法,但没有用:

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

我知道可以使用for循环或查找。但是可以使用gnu cp命令吗?

Answers:


106

否,cp可以复制多个来源,但只能复制到一个目标。您需要安排cp多次调用-每个目标一次-要执行的操作;如您所说,使用循环或其他工具。


感谢你的回答!现在,我考虑了一下,没有额外的标志(不存在),cp将不知道源是什么,DEST目录是什么。
汤姆·费纳

10
这不是正确的答案。请参阅Robert Gamble的答案。
PlagueHammer 2013年

23
@夜曲:我说的那一部分不正确?罗伯特给出了一个使用另一个工具多次调用cp的示例,正​​如我建议的那样。有很多可能的解决方案,涉及使用其他工具或构造来实现这一目标,但OP确实表明他已经意识到这是可能的。
moonshadow

2
遗憾的是,对于cp(和scp)支持该功能将非常有用。但是我们可以使用tee进行拆分。superuser.com/questions/32630/...
西蒙

4
@moonshadow:当然,您的答案是正确的。我认为PlagueHammer想要说在这种情况下,其他答案更为有用。也许您也可以在答案中包含类似内容?
2015年

585

您不能cp独自做到这一点,但可以结合cp使用xargs

echo dir1 dir2 dir3 | xargs -n 1 cp file1

将复制file1dir1dir2dir3xargs将调用cp3次以执行此操作,xargs有关详细信息,请参见手册页。


3
有关xargs的详细信息:cyberciti.biz/faq/…–
克里斯·比尔

24
@西蒙怎么这样?“您不能一个人做到这一点cp”仅仅是因为尝试通过提出另一种方式来尝试提供帮助并不意味着问题没有得到解决。
妮可

3
@NickC提问者指定:“我知道可以使用for循环或查找。但是可以使用gnu cp命令吗?” 好的答案是被接受的答案。
西蒙(Simon)

25
根据他们是否从技术上回答问题来规定接受答案将是令人厌恶的,而且实际上没有用。
西洋双陆棋

4
很有帮助!对于像我这样的其他初学者:您不能将regex与cp一起使用,但是可以在此命令的第一部分(例如echo dir[1-3] | xargs -n 1 cp filename)。
杰森

77

通配符还可以与Roberts代码一起使用

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

和整个注释...例如,要将我桌面上的root拥有的文件(实际上是一个符号链接)移动到所有用户桌面,我首先必须sudo su(否则无法工作),然后使用:echo / home / * /桌面/ | xargs -n 1 cp -av / home / myusername /桌面/文件。
David G

19

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

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

-i的选项cp命令意味着你会被询问是否覆盖文件与当前目录file.dat。尽管它不是一个完全自动化的解决方案,但它为我解决了。


1
虽然增加了-i保护措施是一件好事,但会不会提示您覆盖每个文件?而不是复制到目录?
刺猬

1
@Hedgehog好吧,我认为当目录中有文件并且想要将其复制到目录的子目录时,此命令很有用。在这种情况下,一个文件只能被覆盖一次。感谢您的提问!
Evgeny

2
对我来说,它打印了一系列cp: overwrite问题,但我不必回答任何问题,也没有覆盖文件。
Evgeni Sergeev

还打印了一系列问题,然后将其复制到以dir名称结尾且带有':'字符的文件中,根本没有有效的解决方案,Paul的解决方案运行良好
jgpATs2w 2015年

19

我会用cattee基于我在看到答案/superuser/32630/parallel-file-copy-from-single-source-to-multiple-targets代替cp

例如:

cat inputfile | tee outfile1 outfile2 > /dev/null

1
如果您的目标是不同的物理驱动器(保留一个文件库的两个物理副本,如数字电影的源视频),我刚刚进行的一项粗略测试显示这是最佳的性能。
好奇的人2015年

1
如果您使用的是bash 3.0或更高版本,则可以使用以下范围:cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
Samuel

tee < inputfile outfile1 outfile2 > /dev/nullTaywee的回答也显示了这种有用的模式。请注意,将io-redirection与'<'一起使用,因此不需要从cat进行管道传输。
Alex Telon

10

这些答案似乎都比显而易见的要复杂:

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

一种优雅且for d in */ ; do cp $file "$i" done
可行的方法

9

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

-b如果目录名中有空格,否则xargs会将其分解为其他项,而echo版本存在此问题


6

本身不使用cp,但是...

对于我来说,这是从将(慢速)SD卡上的许多Gopro素材复制到三个(慢速)USB驱动器的上下文中得出的。我只想读取一次数据,因为它要花很长时间。我希望它是递归的。

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

(如果需要更多的输出,可以添加更多这些>()部分。)

我还没有进行基准测试,但是它肯定比cp-in-a-loop(或一堆并行的cp调用)快得多。


5

xargs在Mac OS上使用通配符复制到目录,唯一对我有用的解决方案是在目录名中带有空格:

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

哪里test是要复制的文件
./fs*/*目录复制到

问题是xargs将空格视为新参数,使用-d-E不幸的是,更改定界符字符的解决方案在Mac OS上无法正常工作。


4

如果要在没有分叉命令的情况下执行此操作:

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


2

本质上等效于xargs答案,但是如果要并行执行:

parallel -q cp file1 ::: /foo/ /bar/

因此,例如,将file1复制到当前文件夹的所有子目录(包括递归)中:

parallel -q cp file1 ::: `find -mindepth 1 -type d`

注意:这可能只传达非常明显的用例的任何明显的速度提升,例如,如果每个目标目录是一个不同的磁盘。

它在功能上也类似于xargs的'-P'参数。


0

你不能。

我发现我可以多次使用此功能,因此我已经制作了自己的工具来为我完成此任务。

http://github.com/ddavison/branch

很简单-
branch myfile dir1 dir2 dir3


在许多情况下,我会编写自己的脚本,但如今我倾向于使用太多计算机,因此使它们保持全部同步似乎是一个很大的麻烦。例如,如果只有一种方法可以将云Web目录挂载到/e每台机器上一次,那么我可以编写自己的Powertools并将其永久保存。
Evgeni Sergeev 2014年

0
ls -d */ | xargs -iA cp file.txt A

1
有点解释如何?
分钟

这实际工作,而是一种解释将是巨大的
Ælex

0

假设您要复制fileName.txt到当前工作目录中的所有子目录。

  1. 通过获取所有子目录名称ls并将其保存到某个临时文件中,例如,allFolders.txt

    ls > allFolders.txt
  2. 打印列表并将其传递给command xargs

    cat allFolders.txt | xargs -n 1 cp fileName.txt

0

另一种方法是如下使用cat和tee:

cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>

我认为这将是非常低效的,因为该工作将被分成多个进程(每个目标一个),并且硬盘将在磁盘的不同部分一次写入多个文件。但是,如果要将文件写到几个不同的驱动器中,则此方法可能会非常有效(因为所有副本可能会同时发生)。


0

使用bash脚本

DESTINATIONPATH[0]="xxx/yyy"
DESTINATIONPATH[1]="aaa/bbb"
                ..
DESTINATIONPATH[5]="MainLine/USER"
NumberOfDestinations=6

for (( i=0; i<NumberOfDestinations; i++))
    do
        cp  SourcePath/fileName.ext ${DESTINATIONPATH[$i]}

    done
exit

我对此表示反对。该问题专门要求提供非循环解决方案。
Alex Telon

-1

如果要将多个文件夹复制到多个文件夹,可以执行以下操作:

echo dir1 dir2 dir3 | xargs -n 1 cp -r / path / toyourdir / {subdir1,subdir2,subdir3}


-1

如果所有目标目录都与路径表达式匹配(就像它们都是的子目录一样),path/to则只需将其find与以下命令结合使用cp

find ./path/to/* -type d -exec cp [file name] {} \;

而已。


我对此表示反对。该问题专门要求提供一个未找到的解决方案。
Alex Telon

感谢您对@AlexTelon的深入了解。我想我错过了那一点。我希望您也能保持一致,并对find在线程中使用的其他所有答案都投下反对票。
Mig82

-2

如果您需要将文件复制到哪个文件夹中,则可以将find与一个或多个grps结合使用。例如,要替换在任何子文件夹中出现的favicon.ico,都可以使用:

find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico

-3

这将复制到直接子目录,如果要更深入,请调整-maxdepth参数。

find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html

如果您不想复制到所有目录,则希望可以过滤不感兴趣的目录。复制到所有文件夹的示例 a

find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html

如果要复制到任意/不连续的目录集,则需要Robert Gamble的建议。


-3

我喜欢将文件复制到多个目录中,例如: cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/ 将目录复制到其他目录中: cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/

我知道这就像发出几个命令一样,但是当我想输入1行并走一会儿时,它对我来说效果很好。


7
您正在回答一个6岁的问题,另外15个答案。您的答案必须新颖。我的看法-不是。
Craig S. Anderson

-4

例如,如果您在目标文件夹的父目录中,则可以执行以下操作:

因为我在$(ls)中;执行cp sourcefile $ i; 完成


这个问题说for循环是可能的,所以这实际上并没有添加任何内容。
LJNielsenDk

不赞成投票。切勿尝试解析的输出ls,并始终引用变量。 for i in ./*; do cp sourcefile "$i"; done
sleblanc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.