Как использовать> в команде xargs?

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

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

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

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

Ответ 1

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

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

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

Ответ 2

Решение без 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.

Ответ 3

Я предполагаю, что ваш пример - всего лишь пример и что вам может понадобиться > для других вещей. 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