Я можу знайти файли у папці, що містить певний текстовий рядок за допомогою цієї команди:
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вийти з нього перед читанням до кінця свого аргументу-файлу, що не повинно відбуватися, якщо xargs не буде вбитий сам або не вийде з будь-якої причини, і в цьому випадку я очікую, що ви також побачите помилку про це.
Використовуйте xargsв концерті з mvтретім синтаксисом:mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
Будьте уважні до файлів, що містять спеціальні символи (пробіли, лапки). Якщо це у вашому випадку, фільтрація списку за допомогою sed(додавання лапок навколо назви файлів за допомогою s/^/'/;s/$/'/) може допомогти, але ви повинні бути впевнені, ці цитати не відображатимуться у назви файлів. GNU grepмає -Z/ --nullопцію для припинення імен файлів NUL.
Альтернативою третьому синтаксису для mvє використання xargsз рядком-заповнювачем ( -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 \;
Примітки:
Ви сказали "string" не "pattern", тому -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"/ зовнішній /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name