78

我有一个源输入input.txt

a.txt
b.txt
c.txt

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

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

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

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

它给

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

但我想要

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

任何的想法?

4

13 回答 13

147

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

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

输出将是:

this is first:argument1 second:argument2 third:argument3
于 2014-09-02T12:24:13.977 回答
38

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

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}

或者:

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

但是,如果您的程序采用命令行中可以容纳的参数数量:

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

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

于 2010-09-25T18:49:35.173 回答
22

怎么样:

echo $'a.txt\nb.txt\nc.txt' | xargs -n 3 sh -c '
   echo my-program --file="$1" --file="$2" --file="$3"
' argv0
于 2010-09-22T16:20:40.057 回答
8

如果您使用两个 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
于 2018-04-20T21:52:06.263 回答
7

您可以使用sed为每行添加前缀--file=,然后调用xargs

sed -e 's/^/--file=/' input.txt | xargs my-program
于 2010-09-22T15:28:43.930 回答
5

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

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

这是一种适用于两个参数的方法,但允许更大的灵活性:

cat input.txt | xargs -n 2 | xargs -I{} sh -c 'V="{}"; my-program -file=${V% *} -file=${V#* }'
于 2013-07-31T00:32:25.880 回答
3

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

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

xargs -I X echo --file=X

完整的命令行是:

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

这将像

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

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


实际上,在我的情况下,我需要首先找到文件并且还需要对它们进行排序,所以我的命令行如下所示:

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

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

  • some*pattern必须引用,否则 shell 会在传递给find.
  • -print0, 然后-z最后-0使用空分隔符来确保正确处理带有空格或其他有线名称的文件。

但是请注意,我还没有深入测试它。虽然它似乎正在工作。

于 2016-02-01T13:54:43.753 回答
2

xargs 不能那样工作。尝试:

  我的程序 $(sed -e 's/^/--file=/' input.txt)
于 2010-09-22T16:16:57.620 回答
1

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

echo my-program `xargs --arg-file input.txt -i echo -n " --file "{}`
于 2010-09-22T14:55:20.577 回答
1

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

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

例子:

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

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

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

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

干杯!

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

于 2012-02-02T05:21:49.167 回答
1

实际上,这相对容易:

... | sed 's/^/--prefix=/g' | xargs echo | xargs -I PARAMS your_cmd PARAMS

sed 's/^/--prefix=/g'是可选的,以防您需要在每个参数前面加上一些 --prefix=。

xargs echo参数行列表(每行一个参数)转换为单行中的参数列表,并xargs -I PARAMS your_cmd PARAMS允许您运行命令,将参数放置在您想要的任何位置。

您需要的也是如此cat input.txt | sed 's/^/--file=/g' | xargs echo | xargs -I PARAMS my-program PARAMS(假设 input.txt 中的所有行都很简单,并且每行都符合单个参数值)。

于 2018-01-10T09:30:43.867 回答
1

如果您不知道文件的数量,还有另一种很好的方法:

my-program $(find . -name '*.txt' -printf "--file=%p ")
于 2021-04-01T10:39:57.967 回答
0

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

for line in $(< input.txt) ; do echo --file=$line ; done | xargs echo my-program
于 2014-12-23T09:00:10.537 回答