Я могу найти файлы в папке, содержащей определенную текстовую строку, с помощью этой команды:
grep -lir 'string' ~/directory/*
Как переместить файлы, которые появляются в результате выше, в другое место?
Я могу найти файлы в папке, содержащей определенную текстовую строку, с помощью этой команды:
grep -lir 'string' ~/directory/*
Как переместить файлы, которые появляются в результате выше, в другое место?
Ответы:
Как всегда остерегайтесь grep -r
. -r
не является стандартным вариантом, и в некоторых реализациях, таких как все, кроме самых последних версий GNU grep
, он следует по символическим ссылкам при спуске по дереву каталогов, что, как правило, не то, что вам нужно, и может иметь серьезные последствия, если, например, есть символическая ссылка на "/ "где-то в дереве каталогов.
В философии Unix вы используете команду для поиска в каталогах файлов, а другую - для просмотра ее содержимого.
Используя инструменты GNU, я бы сделал:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
Но даже в этом случае остерегайтесь состояния гонки и возможных проблем безопасности, если вы запускаете его как один пользователь в каталоге, доступном для записи другому пользователю.
xargs
выхода перед чтением до конца его arg-файла, что не должно произойти, если xargs не будет уничтожен сам или не завершится неудачей по любой причине, и в этом случае я ожидаю, что вы также увидите ошибку об этом.
Использование 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.
Если имена ваших файлов не содержат специальных символов (пробел или \[*?
), используйте подстановку команд :
mv `grep -lir 'string' ~/directory/*` destination/
Использование только POSIX указанных особенностей, и не делая ни одного предположения о именах файлов:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
Примечания:
Вы сказали «строка», а не «шаблон», поэтому -F
опция (поиск по фиксированной строке) grep
кажется подходящей.
Если каталог назначения находится где-либо внутри каталога поиска, у вас могут быть неприятные условия гонки.
Используя GNU параллельно :
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht / @ lin-dong за оригинальный ответ xargs.
Предположим, что у вас есть каталог назначения как «внешний» и вам нужно переместить все файлы XLS, вы можете попробовать следующую команду
sudo mv find /var/log/ -type f -name "*.xls"
/ external /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name