cat a.txt | xargs -I % echo %
在上面的例子中,xargs使用echo %作为命令参数。但在某些情况下,我需要多个命令来处理参数,而不是一个。例如:
cat a.txt | xargs -I % {command1; command2; ... }
但是xargs不接受这种形式。我知道的一种解决方案是,我可以定义一个函数来包装命令,但我想避免这样做,因为它很复杂。有没有更好的解决方案?
cat a.txt | xargs -I % echo %
在上面的例子中,xargs使用echo %作为命令参数。但在某些情况下,我需要多个命令来处理参数,而不是一个。例如:
cat a.txt | xargs -I % {command1; command2; ... }
但是xargs不接受这种形式。我知道的一种解决方案是,我可以定义一个函数来包装命令,但我想避免这样做,因为它很复杂。有没有更好的解决方案?
当前回答
使用GNU Parallel,你可以做到:
cat a.txt | parallel 'command1 {}; command2 {}; ...; '
出于安全原因,建议您使用包管理器 安装。但如果你做不到,你可以用这10秒 安装。
10秒安装会尝试做一个完整的安装;如果 失败了,个人安装;如果那失败了,一个最小值 安装。
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
其他回答
我更喜欢允许试运行模式的样式(没有| sh):
cat a.txt | xargs -I % echo "command1; command2; ... " | sh
管道也适用:
cat a.txt | xargs -I % echo "echo % | cat " | sh
我做的一件事是添加到.bashrc/。配置此功能:
function each() {
while read line; do
for f in "$@"; do
$f $line
done
done
}
然后你就可以做
... | each command1 command2 "command3 has spaces"
它比xargs或-exec更简洁。如果还需要这种行为,还可以修改该函数,将读取的值插入到每个命令中的任意位置。
试试这个:
git config --global alias.all '!f() { find . -d -name ".git" | sed s/\\/\.git//g | xargs -P10 -I{} git --git-dir={}/.git --work-tree={} $1; }; f'
它并行运行10个线程,并执行任何你想要在文件夹结构中全部回购的git命令。无论回购是1层还是n层。
例句:get all pull
这似乎是最安全的版本。
tr '[\n]' '[\0]' < a.txt | xargs -r0 /bin/bash -c 'command1 "$@"; command2 "$@";' ''
(可以删除-0,并将tr替换为重定向(或者可以将文件替换为空分隔文件)。它主要是在那里,因为我主要使用xargs查找与-print0输出)(这可能也与xargs版本没有-0扩展名有关)
这是安全的,因为args在执行时将参数作为数组传递给shell。当使用["$@"][1]获得所有这些进程时,shell(至少是bash)会将它们作为未更改的数组传递给其他进程
如果你用…| xargs -r0 -I{} bash -c 'f="{}";命令"$f";' ",如果字符串包含双引号,则赋值将失败。这对于每个使用-i或-i的变体都是正确的。(由于它被替换为字符串,您总是可以通过在输入数据中插入意外字符(如引号、反引号或美元符号)来注入命令)
如果命令一次只能接受一个参数:
tr '[\n]' '[\0]' < a.txt | xargs -r0 -n1 /bin/bash -c 'command1 "$@"; command2 "$@";' ''
或者用更少的进程:
tr '[\n]' '[\0]' < a.txt | xargs -r0 /bin/bash -c 'for f in "$@"; do command1 "$f"; command2 "$f"; done;' ''
如果您有GNU xargs或其他带有-P扩展名的文件,并且希望并行运行32个进程,每个进程每个命令的参数不超过10个:
tr '[\n]' '[\0]' < a.txt | xargs -r0 -n10 -P32 /bin/bash -c 'command1 "$@"; command2 "$@";' ''
这对于输入中的任何特殊字符都应该是健壮的。(如果输入是空分隔的。)如果某些行包含换行符,tr版本将得到一些无效的输入,但对于换行符分隔的文件,这是不可避免的。
bash -c的第一个空白参数是由于:(来自bash手册页)(感谢@clacke)
-c If the -c option is present, then commands are read from the first non-option argument com‐
mand_string. If there are arguments after the command_string, the first argument is assigned to $0
and any remaining arguments are assigned to the positional parameters. The assignment to $0 sets
the name of the shell, which is used in warning and error messages.
使用GNU Parallel,你可以做到:
cat a.txt | parallel 'command1 {}; command2 {}; ...; '
出于安全原因,建议您使用包管理器 安装。但如果你做不到,你可以用这10秒 安装。
10秒安装会尝试做一个完整的安装;如果 失败了,个人安装;如果那失败了,一个最小值 安装。
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh