用多个命令作为参数的xargs

cat a.txt | xargs -I % echo % 

在上面的例子中,xargs将echo %作为命令参数。 但在某些情况下,我需要多个命令来处理,而不是一个,例如:

 cat a.txt | xargs -I % {command1; command2; ... } 

但是xargs不接受这种forms。 我知道的一个解决scheme是我可以定义一个函数来封装这些命令,但它不是pipe道,我不喜欢它。 还有其他解决scheme吗?

 cat a.txt | xargs -I % sh -c 'command1; command2; ...' 

请注意,这是一个无用的猫 。 我会把它写成:

 < a.txt xargs -I % sh -c 'command1; command2; ...' 

(是的,redirect可以在命令的开头。)

假定command1和/或command2将包含一个或多个%字符; 否则就不会有太多的指向xargs-I %选项。

使用GNU Parallel,您可以执行以下操作:

 cat a.txt | parallel 'command1 {}; command2 {}; ...; ' 

观看介绍video以了解更多信息: https : //www.youtube.com/playlist?list = PL284C9FF2488BC6D1

Keith答案是+1 ,因为它符合OP的要求。

这只是没有xargs和cat的另一种方法:

 while read stuff; do command1 "$stuff" command2 "$stuff" ... done < a.txt 

我做的一件事是添加到.bashrc / .profile这个函数:

 function each() { while read line; do for f in "$@"; do $f $line done done } 

那么你可以做类似的事情

 ... | each command1 command2 "command3 has spaces" 

这比xargs或-exec的冗长。 如果你还需要这个行为的话,你也可以修改这个函数来把读取的值插入到命令的任意位置。

您可以使用

 cat file.txt | xargs -i sh -c 'command {} | command2 {} && command3 {}' 

{} =文本文件上每行的variables

另一个可行的解决scheme,对我来说是类似的 –

 cat a.txt | xargs bash -c 'command1 $@; command2 $@' bash 

注意最后的“bash” – 我认为它是作为argv [0]传递给bash的。 如果没有这个语法,每个命令的第一个参数就会丢失。 这可能是任何单词。

例:

 cat a.txt | xargs -n 5 bash -c 'echo -n `date +%Y%m%d-%H%M%S:` ; echo " data: " $@; echo "data again: " $@' bash 

晚会有点迟。

我使用下面的格式在迁移前用成千上万的小文件压缩我的目录。 如果你不需要单引号里面的命令,它应该工作。

经过一些修改,我相信这对别人有用。 在Cygwin (babun)testing

 find . -maxdepth 1 ! -path . -type d -print0 | xargs -0 -I @@ bash -c '{ tar caf "@@.tar.lzop" "@@" && echo Completed compressing directory "@@" ; }' 

find . 在这里find
-maxdepth 1不要进入子目录
! -path . 排除。 /当前目录path
-type d只匹配目录
-print0以空字节\ 0分隔输出
| xargs | xargspipe道xargs
-0input是空分隔的字节
-I @@占位符是@@。 用inputreplace@@。
bash -c '...'运行Bash命令
{...}命令分组
&&仅当前一个命令成功退出时才执行下一个命令(退出0)

决赛 很重要,否则会失败。

输出:

 Completed compressing directory ./Directory1 with meta characters in it Completed compressing directory ./Directory2 with meta characters in it Completed compressing directory ./Directory3 with meta characters in it 

我现在的BKM是这样的

 ... | xargs -n1 -I % perl -e 'system("echo 1 %"); system("echo 2 %");' 

不幸的是,这使用perl,这是不太可能安装比bash; 但它处理更多的input,接受的答案。 (我欢迎一个不依赖perl的无处不在的版本。)

基思·汤普森的build议

  ... | xargs -I % sh -c 'command1; command2; ...' 

非常棒 – 除非在input中有shell注释字符#,在这种情况下,第一个命令的一部分和第二个命令的全部将被截断。

如果input来自文件系统列表(例如ls或find),并且编辑器使用名称中的#创build临时文件,那么散列#就相当普遍。

问题的例子:

 $ bash 1366 $> /bin/ls | cat #Makefile# #README# Makefile README 

哎呀,这是问题所在:

 $ bash 1367 $> ls | xargs -n1 -I % sh -i -c 'echo 1 %; echo 2 %' 1 1 1 1 Makefile 2 Makefile 1 README 2 README 

啊,那好些

 $ bash 1368 $> ls | xargs -n1 -I % perl -e 'system("echo 1 %"); system("echo 2 %");' 1 #Makefile# 2 #Makefile# 1 #README# 2 #README# 1 Makefile 2 Makefile 1 README 2 README $ bash 1369 $> 

我更喜欢风格,允许空运行模式(没有| sh ):

 cat a.txt | xargs -I % echo "command1; command2; ... " | sh 

与pipe道一起工作:

 cat a.txt | xargs -I % echo "echo % | cat " | sh