带有多个参数的xargs

How*_*ard 53 linux bash shell xargs command-line-arguments

我有一个源输入,input.txt

a.txt
b.txt
c.txt
Run Code Online (Sandbox Code Playgroud)

我想将这些输入提供给程序,如下所示:

my-program --file=a.txt --file=b.txt --file=c.txt
Run Code Online (Sandbox Code Playgroud)

所以我尝试使用xargs,但没有运气.

cat input.txt | xargs -i echo "my-program --file"{}
Run Code Online (Sandbox Code Playgroud)

它给

my-program --file=a.txt
my-program --file=b.txt
my-program --file=c.txt
Run Code Online (Sandbox Code Playgroud)

但我想要

my-program --file=a.txt --file=b.txt --file=c.txt
Run Code Online (Sandbox Code Playgroud)

任何的想法?

小智 85

不要听他们所有人:)只看这个例子:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2' | xargs
Run Code Online (Sandbox Code Playgroud)

输出将是

this is first:argument1 second:argument2 third:argument3
Run Code Online (Sandbox Code Playgroud)

  • 哈."不要听他们所有人"我笑. (16认同)
  • 如果您尝试在OSX上执行此操作,请使用-L1,例如`echo argument1 argument2 argument3 | xargs -L1 bash -c'echo这是第一个:$ 0秒:$ 1第三个:$ 2'| xargs` (8认同)
  • 为什么最后需要第二次连接到xargs的管道? (8认同)
  • 但我认为这个答案是不正确的.该文件有3行,但在这个答案中,1行有3个参数! (3认同)
  • @LondonRob `-l` 表示“每个命令行最多使用 MAX-LINES 个非空白输入行”。如果未指定,则默认为 1。`bash` 与 `-l` 无关。我们需要 bash 将一行字符串 `argument1 argument2 argument3` 用空格分隔为 3 个不同的参数。xargs 不会自动执行此操作。 (2认同)

Ole*_*nge 25

到目前为止,给出的解决方案都没有正确处理包含空格的文件名.如果文件名包含'或',有些甚至会失败.如果您的输入文件是由用户生成的,那么您应该为令人惊讶的文件名做好准备.

GNU Parallel很好地处理这些文件名,并为您提供(至少)3种不同的解决方案.如果你的程序只有3个且只有3个参数,那么这将有效:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -N 3 my-program --file={1} --file={2} --file={3}
Run Code Online (Sandbox Code Playgroud)

要么:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo a2.txt; echo b2.txt; echo c2.txt;) |
parallel -X -N 3 my-program --file={}
Run Code Online (Sandbox Code Playgroud)

但是,如果您的程序采用了与命令行相同的参数:

(echo a1.txt; echo b1.txt; echo c1.txt;
 echo d1.txt; echo e1.txt; echo f1.txt;) |
parallel -X my-program --file={}
Run Code Online (Sandbox Code Playgroud)

观看介绍视频以了解更多信息:http://www.youtube.com/watch?v = OpaiGYxkSuQ

  • 有趣 - 不知道 GNU Parallel。Bash 是一个健全的 shell;您不需要在管道后放置反斜杠来告诉它命令的其余部分在下一行。 (2认同)
  • 实用程序的parallel并不总是可用,尤其是在普通的unix中,如果可能,需要安装。有一些有趣的解决方案[下面](http://stackoverflow.com/a/25623391/2969544),可通过standart unix工具获得。 (2认同)

小智 18

怎么样:

echo $'a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="$1" --file="$2" --file="$3"
' argv0
Run Code Online (Sandbox Code Playgroud)


Bar*_*Sas 6

您可以使用sed前缀--file=到每一行,然后调用xargs:

sed -e 's/^/--file=/' input.txt | xargs my-program
Run Code Online (Sandbox Code Playgroud)


jjo*_*jjo 6

如果您使用两个 xargs 调用会更简单:第一个将每一行转换为--file=...,第二个实际执行 xargs 操作 ->

$ cat input.txt | xargs -I@ echo --file=@ | xargs echo my-program
my-program --file=a.txt --file=b.txt --file=c.txt
Run Code Online (Sandbox Code Playgroud)


mah*_*y67 5

这是一个使用sed用于三个参数的解决方案,但其局限性在于它对每个参数应用相同的转换:

cat input.txt | sed 's/^/--file=/g' | xargs -n3 my-program
Run Code Online (Sandbox Code Playgroud)

这是一个适用于两个args的方法,但允许更多的灵活性:

cat input.txt | xargs -n 2 | xargs -I{} sh -c 'V="{}"; my-program -file=${V% *} -file=${V#* }'
Run Code Online (Sandbox Code Playgroud)


Ada*_*ura 5

我偶然发现了一个类似的问题,并找到了一个我认为比迄今为止提出的解决方案更好、更干净的解决方案。

xargs我结束的语法是(对于您的示例):

xargs -I X echo --file=X
Run Code Online (Sandbox Code Playgroud)

完整的命令行是:

my-program $(cat input.txt | xargs -I X echo --file=X)
Run Code Online (Sandbox Code Playgroud)

这就像

my-program --file=a.txt --file=b.txt --file=c.txt
Run Code Online (Sandbox Code Playgroud)

已完成(提供input.txt包含示例中的数据)。


实际上,就我而言,我需要首先找到文件,并且还需要对它们进行排序,因此我的命令行如下所示:

my-program $(find base/path -name "some*pattern" -print0 | sort -z | xargs -0 -I X echo --files=X)
Run Code Online (Sandbox Code Playgroud)

一些可能不清楚的细节(它们不适合我):

  • some*pattern必须加引号,否则 shell 会在传递到 之前对其进行扩展find
  • -print0,然后-z最后-0使用空分隔来确保正确处理带有空格或其他连线名称的文件。

但请注意,我还没有对其进行深入测试。尽管它似乎正在发挥作用。