Команда Grep, чтобы найти файлы, содержащие текстовую строку и переместить их


15

Я могу найти файлы в папке, содержащей определенную текстовую строку, с помощью этой команды:

grep -lir 'string' ~/directory/*

Как переместить файлы, которые появляются в результате выше, в другое место?


Вот. grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name
Алан Донг

Ответы:


10

Как всегда остерегайтесь grep -r. -rне является стандартным вариантом, и в некоторых реализациях, таких как все, кроме самых последних версий GNU grep, он следует по символическим ссылкам при спуске по дереву каталогов, что, как правило, не то, что вам нужно, и может иметь серьезные последствия, если, например, есть символическая ссылка на "/ "где-то в дереве каталогов.

В философии Unix вы используете команду для поиска в каталогах файлов, а другую - для просмотра ее содержимого.

Используя инструменты GNU, я бы сделал:

xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
  ) mv -i --target-directory /dest/dir

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


это дает мне ошибку find: `grep 'завершается сигналом 13. есть идеи, что происходит не так?
Рина Парех

@ReenaParekh, это будет SIGPIPE. Это может произойти только в случае xargsвыхода перед чтением до конца его arg-файла, что не должно произойти, если xargs не будет уничтожен сам или не завершится неудачей по любой причине, и в этом случае я ожидаю, что вы также увидите ошибку об этом.
Стефан Шазелас

15

Использование xargsсовместно с mvтретьим синтаксисом «S:mv [OPTION]... -t DIRECTORY SOURCE...

grep -lir 'string' ~/directory/* | xargs mv -t DEST

Будьте осторожны с файлами, содержащими специальные символы (пробелы, кавычки). Если это ваш случай, фильтрация списка с sed(добавление кавычек вокруг имен файлов с s/^/'/;s/$/'/помощью) может помочь, но вы должны быть уверены, что эти кавычки не появятся в именах файлов. GNU grepимеет параметр -Z/ --nullдля NUL-конца имен файлов.

Альтернативой третьему синтаксису для mvявляется использование xargsс заполнителем string ( -I).

Другой вариант - подстановка команд - $( )или обратные галочки ``(в bash), как указано в ответе ire_and_curses.


3
Gnu grep поддерживает флаг -Z для разделения имен файлов нулевым байтовым символом, который при использовании вместе с флагом -0 для xargs может обойти упомянутую вами проблему специальных символов
iruvar

@ChandraRavoori спасибо, я обновил ответ.
Петер


2

Использование только POSIX указанных особенностей, и не делая ни одного предположения о именах файлов:

find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;

Примечания:

Вы сказали «строка», а не «шаблон», поэтому -Fопция (поиск по фиксированной строке) grepкажется подходящей.

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

POSIX спецификации для grep

POSIX спецификации для find


Это может быть лучшим решением для Macos / BSD
Али

0

Используя GNU параллельно :

grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'

ht / @ lin-dong за оригинальный ответ xargs.


Было бы неплохо, если бы вы указали ответ @ lindong в комментариях более года назад.
roaima

0

Предположим, что у вас есть каталог назначения как «внешний» и вам нужно переместить все файлы XLS, вы можете попробовать следующую команду

sudo mv find /var/log/ -type f -name "*.xls"/ external /

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.