Answers:
对于单个文件,您可以tee
用来复制到多个位置:
cat <inputfile> | tee <outfile1> <outfile2> > <outfile3>
或者,如果您更喜欢已简化的版本:
tee <outfile1> <outfile2> > <outfile3> < <inputfile>
请注意,正如丹尼斯在注释tee
输出中指出的那样,stdout
以及列出的文件,因此在上面的示例中使用重定向指向文件3。您也可以将其重定向到/dev/null
以下位置-这具有使命令行中的文件列表更一致的优点(这可能使编写可变数量文件的解决方案更加容易),但效率较低(尽管效率差小:关于与使用之间的差cat
版本或版本,而不cat
):
cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null
您可能find
很容易将上述方法之一结合起来,以便在一个目录中处理多个文件,而对在目录结构中分散的文件进行操作则不那么容易。否则,您可能只需要将多个复制操作作为单独的任务并行关闭,并希望OS磁盘缓存足够明亮和/或足够大,以使每个并行任务都使用从第一个缓存的读取数据,而不是导致驱动器磁头ing不休。
可用性:tee
通常在标准Linux设置和其他与UNIX或类似的Unix系统上可用,通常作为GNU“ coreutils”软件包的一部分。如果使用Windows(未指定您的问题),则应在各种Windows端口(例如Cygwin)中找到它。
进度信息:由于从光学介质复制大文件可能需要一些时间(或通过慢速网络,甚至从本地快速介质中复制甚至更大的文件),因此进度信息可能会很有用。在命令行上,我倾向于使用管道查看器(在大多数Linux发行版和许多Windows端口集合中可用,并且在不直接可用的地方很容易编译自己)-只需替换cat
为pv
:
pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>
tee
也会输出到stdout,因此您可能要这样做,tee outputfile1 outputfile2 < inputfile > /dev/null
因为将二进制文件输出到终端可能会产生噪音,并且会干扰其设置。
tar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
对于Windows:
n2ncopy将执行以下操作:
对于Linux:
cp
单独的命令可以从多个源复制,但不幸的是不能从多个目标复制。您将需要在某种循环中多次运行它。您可以使用像这样的循环并将所有目录名放在文件中:
OLDIFS=$IFS
IFS=$'\n'
for line in $(cat file.txt):
do
cp file $line
done
IFS=$OLDIFS
或使用xargs:
echo dir1 dir2 dir3 | xargs -n 1 cp file1
这两个都允许您复制整个目录/多个文件。此StackOverflow文章中也对此进行了讨论。
根据类似问题的答案,另一种方法是使用GNU Parallelcp
一次运行多个实例:
parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3
上面的命令会将文件1并行复制到所有三个目标文件夹
瑞安·汤普森(Ryan Thompson)的解决方案:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
很有道理:如果目标目录的写入速度大致相同,则srcfile将仅从磁盘读取一次。其余时间将从缓存中读取。
我会更概括一些,因此您还会得到子目录:
for x in dest1 dest2 dest3; do cp -a srcdir $x &; done; wait;
如果dest dirs的写入速度非常不同(例如,一个在ram磁盘上,另一个在NFS上),则您可能会看到在写入时将srcdir复制到dest1时读取的部分srcdir不再在磁盘高速缓存中目标2。
根据这个答案:https : //superuser.com/a/1064516/702806
更好的解决方案是使用tar
和tee
。该命令更为复杂,但tar
似乎非常强大,可以传输,并且只需要读取一次即可。
tar -c /source/dirA/ /source/file1 | tee >(cd /foo/destination3/; tar -x) >(cd /bar/destination2/; tar -x) >(cd /foobar/destination1/; tar -x) > /dev/null
要在脚本中使用它,您可能需要使用以下命令启动脚本 bash -x script.sh
tar
是它将自动复制(保留)文件属性(例如,修改日期/时间,(保护)模式以及潜在的ACL,所有者/组(如果有特权),SELinux)上下文(如果适用),扩展属性(如果适用)等)……………………PS为什么用户需要使用bash -x
?
#!/bin/sh
在脚本的开头使用了该命令,但是不接受该命令的语法。您可以使用bash -x
或#!/bin/bash
在文件的开头。我不知道为什么sh
和bash
解释之间会有区别。
在bash中:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;