Linux 带有多个参数的 xargs

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3770432/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:36:37  来源:igfitidea点击:

xargs with multiple arguments

linuxbashshellcommand-line-argumentsxargs

提问by Howard

I have a source input, input.txt

我有一个源输入,input.txt

a.txt
b.txt
c.txt

I want to feed these input into a program as the following:

我想将这些输入输入到程序中,如下所示:

my-program --file=a.txt --file=b.txt --file=c.txt

So I try to use xargs, but with no luck.

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

cat input.txt | xargs -i echo "my-program --file"{}

It gives

它给

my-program --file=a.txt
my-program --file=b.txt
my-program --file=c.txt

But I want

但我想要

my-program --file=a.txt --file=b.txt --file=c.txt

Any idea?

任何的想法?

采纳答案by Ole Tange

None of the solutions given so far deals correctly with file names containing space. Some even fail if the file names contain ' or ". If your input files are generated by users, you should be prepared for surprising file names.

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

GNU Paralleldeals nicely with these file names and gives you (at least) 3 different solutions. If your program takes 3 and only 3 arguments then this will work:

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}

Or:

或者:

(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={}

If, however, your program takes as many arguments as will fit on the command line:

但是,如果您的程序需要尽可能多的参数以适合命令行:

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

Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ

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

回答by aioobe

It's because echoprints a newline. Try something like

这是因为echo打印换行符。尝试类似

echo my-program `xargs --arg-file input.txt -i echo -n " --file "{}`

回答by Bart Sas

You can use sedto prefix --file=to each line and then call xargs:

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

sed -e 's/^/--file=/' input.txt | xargs my-program

回答by Burton Samograd

xargs doesn't work that way. Try:

xargs 不能那样工作。尝试:

  myprogram $(sed -e 's/^/--file=/' input.txt)

回答by yabt

How about:

怎么样:

echo $'a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="" --file="" --file=""
' argv0

回答by HoNgOuRu

I was looking for a solution for this exact problem and came to the conclution of coding a script in the midle.

我正在为这个确切的问题寻找解决方案,并得出了在 midle 中编写脚本的结论。

to transform the standard output for the next example use the -n '\n' delimeter

要转换下一个示例的标准输出,请使用 -n '\n' 分隔符

example:

例子:

 user@mybox:~$ echo "file1.txt file2.txt" | xargs -n1 ScriptInTheMiddle.sh

 inside the ScriptInTheMidle.sh:
 !#/bin/bash
 var1=`echo  | cut -d ' ' -f1 `
 var2=`echo  | cut -d ' ' -f2 `
 myprogram  "--file1="$var1 "--file2="$var2 

For this solution to work you need to have a space between those arguments file1.txt and file2.txt, or whatever delimeter you choose, one more thing, inside the script make sure you check -f1 and -f2 as they mean "take the first word and take the second word" depending on the first delimeter's position found (delimeters could be ' ' ';' '.' whatever you wish between single quotes . Add as many parameters as you wish.

为了让这个解决方案起作用,你需要在这些参数 file1.txt 和 file2.txt 之间留一个空格,或者你选择的任何分隔符,还有一件事,在脚本中确保你检查 -f1 和 -f2,因为它们的意思是“把第一个单词并取第二个单词”,具体取决于找到的第一个分隔符的位置(分隔符可以是 ' ' ';' '.' 单引号之间您希望的任何内容。添加任意数量的参数。

Problem solved using xargs, cut , and some bash scripting.

使用 xargs、cut 和一些 bash 脚本解决了问题。

Cheers!

干杯!

if you wanna pass by I have some useful tips http://hongouru.blogspot.com

如果你想路过我有一些有用的提示http://hongouru.blogspot.com

回答by maharvey67

Here is a solution using sed for three arguments, but is limited in that it applies the same transform to each argument:

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

cat input.txt | sed 's/^/--file=/g' | xargs -n3 my-program

Here's a method that will work for two args, but allows more flexibility:

这是一种适用于两个 args 的方法,但具有更大的灵活性:

cat input.txt | xargs -n 2 | xargs -I{} sh -c 'V="{}"; my-program -file=${V% *} -file=${V#* }'

回答by sauliux

dont listen to all of them :) just look at this example:

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

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:
this is first:argument1 second:argument2 third:argument3
second: third:' | xargs

output will be

输出将是

for line in $(< input.txt) ; do echo --file=$line ; done | xargs echo my-program

回答by conny

Nobody has mentioned echoing out from a loop yet, so I'll put that in for completeness sake (it would be my second approach, the sed one being the first):

还没有人提到从循环中回显,所以为了完整起见,我将其放入(这将是我的第二种方法,sed 是第一种方法):

xargs -I X echo --file=X

回答by Adam Badura

I stumbled on a similar problem and found a solution which I think is nicer and cleaner than those presented so far.

我偶然发现了一个类似的问题,并找到了一个我认为比目前提供的更好、更简洁的解决方案。

The syntax for xargsthat I have ended with would be (for your example):

xargs我已经结束的语法是(对于你的例子):

my-program $(cat input.txt | xargs -I X echo --file=X)

with a full command line being:

完整的命令行是:

my-program --file=a.txt --file=b.txt --file=c.txt

which will work as if

这将工作好像

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

was done (providing input.txtcontains data from your example).

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



Actually, in my case I needed to first find the files and also needed them sorted so my command line looks like this:

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

##代码##

Few details that might not be clear (they were not for me):

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

  • some*patternmust be quoted since otherwise shell would expand it before passing to find.
  • -print0, then -zand finally -0use null-separation to ensure proper handling of files with spaces or other wired names.
  • some*pattern必须引用,否则 shell 会在传递到find.
  • -print0,然后-z最后-0使用空分隔来确保正确处理带有空格或其他连线名称的文件。

Note however that I didn't test it deeply yet. Though it seems to be working.

但是请注意,我还没有对其进行深入测试。虽然它似乎有效。