如何将 -I 和 -n 与 xargs 结合使用?
How do I combine -I and -n with xargs?
我想使用 find
和 xargs
移动大量文件。通常我会这样做:
find /foo -name 'bar*' | tr '\n' ' ' | xargs -I % echo mv % /dest
但是,当要移动的文件太多时,我达到了传递给 mv
的参数数量的限制。 xargs
有一个 -n
似乎非常适合这个:
$ echo {0..9} | xargs -n 3 echo
0 1 2
3 4 5
6 7 8
9
但是,-I
意味着 -L 1
,所以我不能将 -I
与 -n
一起使用:
$ echo {0..9} | xargs -n 3 -I % echo % /dest
0 1 2 3 4 5 6 7 8 9 /dest
我希望有这样的行为:
$ echo {0..9} | xargs -n 3 -I % echo % /dest
0 1 2 /dest
3 4 5 /dest
6 7 8 /dest
9 /dest
xargs
可以吗?我的机器上没有 GNU Parallel。
mv
命令(至少来自 Linux coreutils)具有方便的 -t
标志,与此用例完美匹配:
find /foo -name 'bar*' | tr '\n' ' ' | xargs mv -t /dest
Above 还支持保留任何没有文件名的奇怪文件名 massaging:
find /foo -name 'bar*' -print0 | xargs -0 mv -t /dest
如果出于任何原因你想像往常一样使用 mv ,下面也可以工作(即使用 sh
scriptlet 到 "consume" 所有参数( $@
)):
find /foo -name 'bar*' | tr '\n' ' ' | xargs sh -c 'mv "$@" /dest' --
使用 GNU Parallel 你会做:
find /foo -name 'bar*' |
parallel -X echo mv {} /dest
这适用于包含“、”和 space 的文件名。如果文件名包含“\n”,则您必须求助于:
find /foo -name 'bar*' --print0 |
parallel -0 -X echo mv {} /dest
如果您的计算机上没有 GNU Parallel,并且您没有以 root 身份安装软件的权限,您可以进行个人安装:
wget https://ftpmirror.gnu.org/parallel/parallel-20180422.tar.bz2
bzip2 -dc parallel-20180422.tar.bz2 | tar xvf -
cd parallel-20180422
./configure --prefix=$HOME && make && make install
或者您可以在装有 GNU Parallel 的机器上使用 --embed
,然后将生成的脚本复制到您的其他机器上:
parallel --embed > new_script
# Change the end of new_script
# Copy new_script to the other machine
如果您要使用 find
查找常规文件,您应该使用 -type f
,否则您可能会找到目录。此处无需使用 xargs
,因为您已经在 find
.
中内置了该功能
使用 GNU mv
:
find /foo -type f -name 'bar*' -exec mv -t /dest {} +
这不会检测到已经存在同名的目标文件。为此,请使用
find /foo -type f -name 'bar*' -exec sh -c '
for name do
destname="/dest/${name##*/}"
if [ ! -f "$destname" ]; then
mv "$name" "$destname"
else
printf '%s exists already, will not copy %s\n' "$destname" "$name" >&2
fi
done' sh {} +
这将拒绝移动会覆盖 /dest
中文件的文件(并报告这些文件)。
这些命令适用于所有有效的 Unix 文件名。
我想使用 find
和 xargs
移动大量文件。通常我会这样做:
find /foo -name 'bar*' | tr '\n' ' ' | xargs -I % echo mv % /dest
但是,当要移动的文件太多时,我达到了传递给 mv
的参数数量的限制。 xargs
有一个 -n
似乎非常适合这个:
$ echo {0..9} | xargs -n 3 echo
0 1 2
3 4 5
6 7 8
9
但是,-I
意味着 -L 1
,所以我不能将 -I
与 -n
一起使用:
$ echo {0..9} | xargs -n 3 -I % echo % /dest
0 1 2 3 4 5 6 7 8 9 /dest
我希望有这样的行为:
$ echo {0..9} | xargs -n 3 -I % echo % /dest
0 1 2 /dest
3 4 5 /dest
6 7 8 /dest
9 /dest
xargs
可以吗?我的机器上没有 GNU Parallel。
mv
命令(至少来自 Linux coreutils)具有方便的 -t
标志,与此用例完美匹配:
find /foo -name 'bar*' | tr '\n' ' ' | xargs mv -t /dest
Above 还支持保留任何没有文件名的奇怪文件名 massaging:
find /foo -name 'bar*' -print0 | xargs -0 mv -t /dest
如果出于任何原因你想像往常一样使用 mv ,下面也可以工作(即使用 sh
scriptlet 到 "consume" 所有参数( $@
)):
find /foo -name 'bar*' | tr '\n' ' ' | xargs sh -c 'mv "$@" /dest' --
使用 GNU Parallel 你会做:
find /foo -name 'bar*' |
parallel -X echo mv {} /dest
这适用于包含“、”和 space 的文件名。如果文件名包含“\n”,则您必须求助于:
find /foo -name 'bar*' --print0 |
parallel -0 -X echo mv {} /dest
如果您的计算机上没有 GNU Parallel,并且您没有以 root 身份安装软件的权限,您可以进行个人安装:
wget https://ftpmirror.gnu.org/parallel/parallel-20180422.tar.bz2
bzip2 -dc parallel-20180422.tar.bz2 | tar xvf -
cd parallel-20180422
./configure --prefix=$HOME && make && make install
或者您可以在装有 GNU Parallel 的机器上使用 --embed
,然后将生成的脚本复制到您的其他机器上:
parallel --embed > new_script
# Change the end of new_script
# Copy new_script to the other machine
如果您要使用 find
查找常规文件,您应该使用 -type f
,否则您可能会找到目录。此处无需使用 xargs
,因为您已经在 find
.
使用 GNU mv
:
find /foo -type f -name 'bar*' -exec mv -t /dest {} +
这不会检测到已经存在同名的目标文件。为此,请使用
find /foo -type f -name 'bar*' -exec sh -c '
for name do
destname="/dest/${name##*/}"
if [ ! -f "$destname" ]; then
mv "$name" "$destname"
else
printf '%s exists already, will not copy %s\n' "$destname" "$name" >&2
fi
done' sh {} +
这将拒绝移动会覆盖 /dest
中文件的文件(并报告这些文件)。
这些命令适用于所有有效的 Unix 文件名。