15

Я хочу удалить все файлы, которые содержат строку foo . Как я могу сделать это, используя bash в Linux?

3 ответа3

31

Вот безопасный способ:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l выводит имена файлов, соответствующие шаблону поиска.
  • -r выполняет рекурсивный поиск шаблона foo в заданном каталоге . ,  Если это не сработает, попробуйте -R .
  • -I (заглавная i) вызывает пропуск двоичных файлов, таких как PDF.
  • -Z гарантирует, что имена файлов заканчиваются на ноль (т. Е. На ноль), так что имя, содержащее пробел, не интерпретируется неправильно (т. Е. Как несколько имен вместо одного).
  • xargs -0 имена файлов из grep в rm -f , отделяя слова нулевыми (nul) байтами (помните параметр -Z из grep).
  • -- часто забывают, но очень важно отметить конец параметров и разрешить удаление файлов, имена которых начинаются с - .

Если вы хотите увидеть, какие файлы будут удалены, просто удалите | xargs -0 rm -f -- part, и отключите опцию Z для grep .

Другой пользователь предложил что-то вроде следующего, которое вы не должны запускать, потому что это небезопасно:

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

Если у меня есть файлы ImportantStuff которые я не хочу удалять, и которые obsolete ImportantStuff содержит foo , тогда я теряю ImportantStuffне obsolete ImportantStuff !) когда я запускаю эту команду, потому что $files разрывается на пробелы, когда она интерпретируется. Таким образом, опасно помещать список имен файлов в скалярную переменную оболочки.

17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

Это рекурсивно ищет файлы, содержащие foo . Второй -exec запускается только в том случае, если первый exec успешно завершен, т.е. если grep совпадает. Dryrun и удалите echo если вывод кажется правильным.

Или в качестве альтернативы

$ find -type f -exec grep -q "foo" {} \; -print

а также

$ find -type f -exec grep -q "foo" {} \; -delete

как предполагает Лекенштейн.

1

Я бы сделал то, что говорит Адриан,

Но я бы добавил границы слов для foo, чтобы случайно не удалить файлы, содержащие "food" (если только он не удаляет все, что содержит food, то, что вам нужно).

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

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

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete

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