使用cp将单个文件复制到多个目录

And*_*rew 12 shell bash cp

这个问题是我之前的问题的续集,使用mkdir.

我正在使用bash外壳。我创建了五十个目录,每个目录都以前缀“s”开头,使用以下命令:

mkdir $(printf "s%02i " $(seq 1 50))
Run Code Online (Sandbox Code Playgroud)

用零填充到第二个数字。也就是说,我获得的目录的形式为s01, s02, ..., s49, s50

现在我想使用cp将单个文件(例如,test.txt)复制到五十个目录中的每一个。是否有可能以类似于上面的方式做到这一点?例如,以下是否可行?我对 Unix/Linux 比较陌生,所以我真的不想尝试这个,直到有人告诉我它是安全的。

cp test.txt $(printf "s%02i.txt " $(seq 1 50))

查看man页面cp,它看起来不像cp支持这样的多个目的地,但是:

NAME
       cp - copy files and directories

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

       Mandatory  arguments  to  long  options are mandatory for short options
       too.
Run Code Online (Sandbox Code Playgroud)

Jim*_*ris 8

您还可以让 shell 使用for循环进行迭代。这是最基本的方法,不依赖于parallel或等外部工具xargs,我发现它最容易理解:

for name in $(printf "s%02i " $(seq 1 50)); do
    mkdir $name
    cp test.txt $name
done
Run Code Online (Sandbox Code Playgroud)

还有一百万种其他方式来写这个,例如:

for name in $(seq -w 1 50); do
    mkdir s$name
    cp test.txt s$name
done
Run Code Online (Sandbox Code Playgroud)

如果您想在执行之前验证将执行的内容,您可以执行一些操作,例如在命令前加上echo,这将打印该行而不是执行它:

for name in $(seq -w 1 50); do
    echo mkdir s$name
    echo cp test.txt s$name
done
Run Code Online (Sandbox Code Playgroud)

输出:

mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.
Run Code Online (Sandbox Code Playgroud)


toj*_*son 7

如果您想使用命令的输出将文件复制到每个目录cp,您可以始终将其通过管道传输到xargs

printf "s%02i " $(seq 1 50) | xargs -n 1 cp test.txt
Run Code Online (Sandbox Code Playgroud)

不应该担心解析输出的安全性,因为您事先知道它的格式和内容——在文件名中遇到元字符和空格的风险在这里并不是真正的问题。

或者,假设目录已经存在,您可以尝试以下操作:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -print0 | xargs -0 -I {} cp test.txt {}
Run Code Online (Sandbox Code Playgroud)

或没有管道:

find . -maxdepth 1 -type d -name 's[0-9][0-9]' -exec cp test.txt {} \;
Run Code Online (Sandbox Code Playgroud)

最后两个命令将查找当前目录中的任何文件并找到cp test.txt它们。该-maxdepth 1选项也将避免接收文件的任何子目录。请注意,'s[0-9][0-9]'匹配s后跟任意两位数字,这意味着如果由于某种原因您s99在 中cwd,它也会收到test.txt.