我在复制不同目录中的许多文件时遇到问题。让我更好地解释一下:
假设我的目录中有以下内容:
$ ls
file1 file2 file3 file4 file5 dir1 dir2 dir3
我想用一个命令复制每个目录*中的每个文件*。我尝试过:
echo dir{1..3} | xargs cp file{1..5} '{}' \;
我的目的是告诉 xargs 处理 echo 中的每个 dir* 并复制处理的输入中的所有文件,但此方法和类似方法不起作用。我想避免使用脚本,因为这是一个我必须对大约 20 个目录重复的任务,并且文件的名称略有不同,所以我更喜欢修改命令而不是脚本。
答案1
echo dir[1-3] | xargs -r -n1 cp file[1-5]
答案2
您在使用 xargs 时犯了一个小错误。如果没有 -n 参数,xargs 会将输入中的所有参数附加到命令中,并且echo dir{1..3}
不会在每个条目之间添加必要的回车符,因此 xargs 会将结果视为一个参数。
xargs 有一个选项 -n 可以限制条目数量,您需要使用 \n 或 \0 作为分隔符列出目录:
find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 -n 1 cp file{1..5}
find 命令将查找当前目录中的所有目录,并使用 \0 作为分隔符(如果目录带有空格,则效果更好),而 xargs 使用 \0 作为分隔符,并且每次仅使用 1 个参数启动该命令。
答案3
如果它们确实有这样的名称,则类似以下内容应该有效:
#!/bin/bash
shopt -s nullglob
for dir in dir*/; do
cp file* "$dir"
done
如果要将所有文件复制到所有目录(无论名称如何):
#!/bin/bash
shopt -s nullglob dotglob
for dir in */; do
for file in *; do
[[ -f $file ]] && cp "$file" "$dir"
done
done
答案4
你快到了。您需要cp
为每个目标目录运行单独的命令,因为cp
只为每个源文件创建一份副本。的主要目的xargs
是通过多个参数运行一个命令,但您可以使用该选项告诉它一次传递一个项目-n
。也是;{} ;
的语法find … -exec
你不需要(也不能使用)它与xargs
.
echo dir{1..3} | xargs -n 1 cp file{1..5}
请注意,只有当您的目录名不包含任何空格或任何字符时\'"
,这才有效,因为xargs
无法判断这些字符是文件名的一部分,并且无法引用和分隔输入文件。不存在任何此类问题的另一种方法是使用 shell 循环:
for d in dirs{1..3}; do
cp file{1..5} "$d"
done
所有这些都假设您可以通过名称轻松区分文件和目录。如果不能,可以通过/
在末尾添加a来匹配目录;例如*/
匹配当前目录中的所有目录,foo[0-9]*/
匹配名称以foo
数字开头的所有目录等。在大多数 shell 中没有类似的方法来仅匹配非目录,但是如果您将目录传递给cp
不带任何参数来告诉它要进行递归复制,目录将被忽略并显示错误消息。
for d in */; do
cp * "$d"
done
在 zsh 中,您可以使用全局限定符仅匹配某些文件类型。
for d in *(/); do
cp *(.) $d
done