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
Любая идея?
Ответы
Ответ 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
используйте нулевое разделение для обеспечения правильной обработки файлов с пробелами или другими проводными именами.
Обратите внимание, что я еще не испытал это глубоко. Хотя кажется, что он работает.