Подтвердить что ты не робот

Xargs с несколькими аргументами

У меня есть исходный ввод, 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

Любая идея?

4b9b3361

Ответ 1

Ни одно из решений, данных до сих пор, не соответствует именам файлов, содержащих пробел. Некоторые даже терпят неудачу, если имена файлов содержат "или". Если ваши входные файлы генерируются пользователями, вы должны быть готовы к неожиданным именам файлов.

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

Ответ 2

Не слушайте их всех:) просто посмотрите на этот пример:

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

вывод будет

this is first:argument1 second:argument2 third:argument3

Ответ 3

Как насчет:

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

Ответ 4

Вы можете использовать sed для префикса --file= для каждой строки, а затем вызвать xargs:

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

Ответ 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#* }'

Ответ 6

Это потому, что echo печатает новую строку. Попробуйте что-то вроде

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

Ответ 7

Я искал решение этой точной проблемы и пришел к заключению в кодировке script в средстве.

чтобы преобразовать стандартный вывод для следующего примера, используйте -n '\n' delimeter

Пример:

 [email protected]:~$ 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 или любым другим дебетоном, который вы выбираете, еще одна вещь, внутри script убедитесь, что вы проверили -f1 и -f2 как они означают "взять первое слово и взять второе слово" в зависимости от найденной первой позиции деминера (разделители могут быть "," ".", что бы вы ни пожелали между одинарными кавычками. Добавьте столько параметров, сколько пожелаете.

Проблема решена с помощью скриптов xargs, cut и некоторых bash.

Ура!

Если вы хотите пройти мимо, у меня есть несколько полезных советов http://hongouru.blogspot.com

Ответ 8

xargs не работает. Попробуйте:

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

Ответ 9

Никто еще не упомянул эхо из цикла, поэтому я поставлю это ради полноты (это будет мой второй подход, первый из которых первый):

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

Ответ 10

Я наткнулся на подобную проблему и нашел решение, которое, по моему мнению, более приятное и чистое, чем те, которые были представлены до сих пор.

Синтаксис для 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 должен быть указан, поскольку в противном случае он должен расширять его до перехода на find.
  • -print0, затем -z и, наконец, -0 используйте нулевое разделение для обеспечения правильной обработки файлов с пробелами или другими проводными именами.

Обратите внимание, что я еще не испытал это глубоко. Хотя кажется, что он работает.