Я могу найти файлы в папке, содержащей определенную текстовую строку, с помощью этой команды:
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