Как использовать> в команде 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