Использование xargs с вводом из файла

41

Скажем, у меня есть файл со следующим

bob
john
sue

Теперь они непосредственно corrospond к (в данном случае) модель URL , такие как http://example.com/persons/bob.tar, john.tar, sue.tar.

Я хотел бы взять эти строки и провести их через xargs. Я не знаю, что передается команде, хотя выполняется. Как получить доступ к параметру либо из приглашения (скажем, я хочу просто отобразить каждую строку, как cat file | xargs echo $PARAM), либо из сценария bash.

Джош К
источник
Я не совсем понимаю вопрос, извините. В частности, я не уверен, что означает «я не знаю, что передается выполняемой команде»
Майкл Мрозек
1
@Michael: Когда вы просматриваете список, xargsон разбивает его на строки и передает каждую строку в команду, верно? Как я могу получить доступ к этому, если мне нужно сказать что-то вроде cat file | xargs curl http://example.com/[PASSED FROM FILE].tar?
Джош К

Ответы:

70

Майкл ответ правильный, и должен решить вашу проблему. Бег

cat file | xargs -I % curl http://example.com/persons/%.tar

загрузит файлы, bob.tar john.tar. sue.tarкак и ожидалось.

НО : кошка здесь бесполезна

скорее используйте:

<file xargs -I % curl http://example.com/persons/%.tar
Стефан
источник
1
В моем примере с одним файлом это может быть не идеально, однако,cat xaa xab xac xad ... xargs ...
Джош К
10
@Josh По какой-то причине люди, как правило, очень серьезно относятся к ненужному использованию кошки; За меня уже дважды проголосовали
Майкл Мрозек
2
для записи, вы получили +1 от меня. Я думаю, что использование catдействительно хорошо, просто хотел бы добавить больше информации ... :)
Stefan
Конечно, это должно быть xargs -I % curl …( опция xargs before curlи ее параметры / аргументы). По крайней мере xargs curl -I %(где -I %это подразумевается как опция для xargs , а не curl ) не является переносимым.
Крис Джонсен
@ Крис, хороший улов, тнкс. исправлено.
Стефан
16

Я думаю, вы спрашиваете, как вставить отдельные строки, извлеченные из xargs'stdin, в середину команды, вместо того, чтобы просто вставлять ее в конец всегда. Если это так, -Iфлаг принимает replacement-stringаргумент; xargsзатем заменим replacement-stringв команде строку, прочитанную из stdin:

$ cat file | xargs -I foobar curl http://example.com/foobar.tar
Михаил Мрозек
источник
Хорошо, как насчет curl http://example.com/foobar.tar > foobar.tar?
Джош К
2
@ Джош К: >это оболочка конструкций, и не будет работать для xargs. С другой стороны, curl -oбудет записывать в именованный файл вместо stdout, как, например, то wget, что делает, так что это, вероятно, то, что вы хотели бы использовать здесь.
Эфимент
9
$ man xargs
...
       --arg-файл = файл
       -файл
              Чтение элементов из файла вместо стандартного ввода. Если вы используете это
              опция, стандартный ввод остается неизменным при выполнении команд. Другие-
              мудро, stdin перенаправляется из / dev / null.
...

Вы также можете установить --delimiter=/ -dна '\n'.


С другой стороны, если вы просто пытаетесь превратить каждую строку в файле в URL,

Файл $ sed -e #. * # http: //example.com/persons/&.tar# '

будет делать, и если вы хотите получить все из них, просто передать это в .| wget -i

ephemient
источник
8

Другой способ с циклом оболочки:

for i in `cat file`; do curl -I http://foo.com/$i; done

Вы также можете запустить каждую итерацию в фоновом режиме, добавив &перед последней точкой с запятой - для очень больших загрузок это может быть удобно

Брэд Клоузи
источник
2
Вы попали в одну из классических ошибок ! <- неработающая ссылка, вот кэшированная версия: Бесполезное использование награды Cat .
Сорпигал
@Sorpigal Этот URL не работает. Что такое «Классическая ошибка»?
starbeamrainbowlabs
@starbeamrainbowlabs - бесполезное использование кошки, я поместил кэшированную версию этой ссылки в комментарии выше.
СЛМ
@starbeamrainbowlabs: Я специально ссылался на Dangerous Backticks , но использование cat также не нужно, если вы переходите на конструкцию while:while IFS= read i ; do curl ... ; done < file
Sorpigal
3

С GNU Parallel вы можете делать:

cat urls | parallel curl {} ">" {/}

Или:

cat persons | parallel curl http://example.com/persons/{}.tar ">" {}.tar

Посмотрите вступительное видео для GNU Parallel, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Оле Танге
источник
1

while read VAR; do ... done цикл простой, но очень универсальный:

while read word; do wget http://example.com/persons/$word; done < file
musiphil
источник
0

Это более общая версия ответа Стефана, но я использую awk в середине, чтобы подготовить точную «строку», которую я хотел бы выполнить xargs. И тогда xargs использует bash, чтобы выполнить настоящую «работу».

Это немного излишне для этого примера, но это общее решение, которое с некоторыми изменениями может решить многие проблемы ...

cat file | awk '{print "curl http://example.com/persons/"$1".tar"}' | xargs -0 bash -c
Johan
источник