5

Мне нужен способ запустить grep для списка файлов, которые могут содержать пробелы в имени файла. В списке файлов без пробелов это довольно просто и легко. Также я знаю, как обращаться с пробелами в именах файлов для find и xargs. Я просто ищу способ использовать grep с командой -print0.

Я ищу текст внутри файла, а не в имени файла ...

Это перечисляет все файлы:

find * -print 0 | xargs -0 -i{} echo {}

но скажите, что я должен сделать grep (или другую команду) между ними.

Это список файлов, которые содержат "Howdy Doody" внутри файла:

find * | xargs grep -l "howdy doody" | xargs -i{} echo {}

Это не работает, grep не знает, как распознать нулевые завершенные строки. Я что-то пропустил на странице grep ?

find * -print0 | xargs grep -l "howdy doody" | xargs -0 -i{} echo {}

2 ответа2

15

Вы ищете "привет дуди" в имени файла или в файле?

# find files with "howdy doody" in the filename
find * -name "*howdy doody*" -print0 | xargs -0 ...

xargs - это то, что вам нужно, чтобы разделить вывод с нулем в конце из find -print0 . В вашем примере echo постороннее; не беспокойся об этом.

# find files containing "howdy doody"
find * -print0 | xargs -0 grep -l "howdy doody"

# find files containing "howdy doody" and do further processing

# multiple xargs version
find * -print0 | xargs -0 grep -l "howdy doody" | xargs -i{} do-something "{}"

# "sh -c" version
find * -print0 | xargs -0 -i{} sh -c 'grep -l "howdy doody" "{}" && do-something "{}"'

# notes: 
#   "sh -c" allows us to run a complex command with a single xargs
#   "{}" handles spaces-in-filename
#   handles any &&, ||, | command linking

Вы также можете запустить команду непосредственно из команды find с помощью команды -exec . Разница в том, что команда find -exec запускает команду один раз для каждого найденного файла; xargs добавляет имена файлов в конец команды (до системного лимита), поэтому она запускает команду меньше раз. Вы можете смоделировать это с помощью xargs -n1 чтобы заставить xargs запускать только одну команду для каждого входа.

# grep once per file
find * -exec grep -l "howdy doody" {} \; | ...
3

Вы можете сделать все это одной командой, используя аргумент -exec чтобы find:

find . -name "*howdy doody*" -exec echo I found file {} hooray \;

Экранированная точка с запятой в конце команды для выполнения требуется командой find .

Или, если вы просматриваете содержимое файлов:

grep -R "howdy doody" *

Это покажет все совпадения текста, добавьте -l в grep, чтобы просто получить список файлов

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .