Как использовать> в команде xargs? - PullRequest
146 голосов
/ 10 мая 2009

Я хочу найти команду bash, которая позволит мне grep каждый файл в каталоге и записать вывод этого grep в отдельный файл. Я думаю, было бы сделать что-то вроде этого

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

но, насколько я знаю, xargs не нравятся двойные кавычки. Однако, если я удаляю двойные кавычки, команда перенаправляет вывод всей команды в один файл с именем «{}». Вместо ряда отдельных файлов.

Кто-нибудь знает способ сделать это с помощью xargs? Я просто использовал этот сценарий grep в качестве примера, чтобы проиллюстрировать мою проблему с xargs, поэтому любые решения, которые не используют xargs, не подходят для меня.

Ответы [ 3 ]

177 голосов
/ 10 мая 2009

Не делайте ошибку, делая это:

sh -c "grep ABC {} > {}.out"

Это будет нарушено при многих условиях, в том числе прикольных имен файлов, и невозможно правильно процитировать. Ваш {} всегда должен быть одним совершенно отдельным аргументом команды, чтобы избежать ошибок внедрения кода. Что вам нужно сделать, это:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

Относится к xargs, а также find.

Кстати, никогда не используйте xargs без опции -0 (если только для очень редкого и контролируемого одноразового интерактивного использования, когда вы не беспокоитесь об уничтожении ваших данных).

Также не разбирайте ls. Когда-либо. Вместо этого используйте globbing или find: http://mywiki.wooledge.org/ParsingLs

Используйте find для всего, что требует рекурсии, и простой цикл с глобусом для всего остального:

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

или нерекурсивный:

for file in *; do grep "$file" > "$file.out"; done

Обратите внимание на правильное использование кавычек.

38 голосов
/ 10 мая 2009

Решение без xargs выглядит следующим образом:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

... и то же самое можно сделать с xargs, получается:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

Редактировать : одиночные кавычки добавлены после замечания lhunath .

14 голосов
/ 10 июня 2010

Полагаю, ваш пример - всего лишь пример, который может вам понадобиться для других вещей GNU Parallel http://www.gnu.org/software/parallel/ может быть вашим спасением. Он не нуждается в дополнительном цитировании, если ваши имена файлов не содержат \ n:

ls | parallel "grep ABC {} > {}.out"

Если у вас есть имена файлов с \ n:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

В качестве дополнительного бонуса вы получаете задания, выполняемые параллельно.

Редактировать.

Вы можете установить GNU Parallel просто:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

Посмотрите вступительные видео, чтобы узнать больше: http://pi.dk/1

10 секунд установки:

wget pi.dk/3 -qO - | sh -x
...