这个问题是我之前问题的续集,使用创建大量目录mkdir
。
我正在使用bash
外壳。我使用以下命令创建了五十个目录,每个目录都以前缀“s”开头:
mkdir $(printf "s%02i " $(seq 1 50))
用零填充到第二个数字。也就是说,我获得的目录的形式为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.
答案1
您还可以让 shell 通过for
循环进行迭代。这是最基本的方法,不依赖于parallel
或等外部工具xargs
,我发现它最容易理解:
for name in $(printf "s%02i " $(seq 1 50)); do
mkdir $name
cp test.txt $name
done
还有一百万种其他的写法,例如:
for name in $(seq -w 1 50); do
mkdir s$name
cp test.txt s$name
done
如果您想在执行之前验证要执行的内容,您可以执行一些操作,例如在命令前面加上echo
,这将打印该行而不是执行它:
for name in $(seq -w 1 50); do
echo mkdir s$name
echo cp test.txt s$name
done
输出:
mkdir s01
cp test.txt s01
mkdir s02
cp test.txt s02
mkdir s03
cp test.txt s03
# etc.
答案2
如果您想使用命令的输出将文件复制到每个目录cp
,您可以随时将其通过管道传输到xargs
:
printf "s%02i " $(seq 1 50) | xargs -n 1 cp test.txt
不应该担心解析输出的安全性,因为您事先知道其格式和内容 - 在文件名中遇到元字符和空格的风险在这里并不是真正的问题。
或者,假设目录已经存在,您可以尝试以下操作:
find . -maxdepth 1 -type d -name 's[0-9][0-9]' -print0 | xargs -0 -I {} cp test.txt {}
或没有管道:
find . -maxdepth 1 -type d -name 's[0-9][0-9]' -exec cp test.txt {} \;
最后两个命令将查找当前目录中的所有文件以及cp
test.txt
它们。该-maxdepth 1
选项将避免任何子目录接收该文件。请注意,'s[0-9][0-9]'
匹配s
后跟任何两个数字,这意味着如果由于某种原因您在s99
中cwd
,它也会收到 的副本test.txt
。
答案3
根据这个:https://stackoverflow.com/questions/195655/how-to-copy-a-file-to-multiple-directories-using-the-gnu-cp-command无法将一个文件复制到多个目的地。检查链接,因为它显示了执行此操作的另一种方法。
答案4
你也可以使用 GNU平行线。假设您位于包含 text.txt 的目录中,并且您的 50 个目录位于/my/50dirs/path
(例如/my/50dirs/path/s01
等/my/50dirs/path/s02
),您将运行:
seq -w 01 50 | parallel -j1 cp text.txt /my/50dirs/path/s{}