Команда 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

Але навіть тоді остерігайтесь умов перегонів та можливих проблем із безпекою, якщо ви запускаєте їх як один користувач у каталозі, на якому може писати інший користувач.


це дає мені знайти помилку: `grep 'припиняється сигналом 13. будь-яка ідея, що йде не так?
Реена Парех

@ReenaParekh, це був би ЗНАЧ. Це відбудеться лише в тому випадку, якщо xargsвийти з нього перед читанням до кінця свого аргументу-файлу, що не повинно відбуватися, якщо xargs не буде вбитий сам або не вийде з будь-якої причини, і в цьому випадку я очікую, що ви також побачите помилку про це.
Стефан Шазелас

15

Використовуйте 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.


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

@ChandraRavoori спасибі, я оновив відповідь.
петерф

7

Якщо імена ваших файлів не містять жодних спеціальних символів (пробіл або \[*?), використовуйте заміну команд :

mv `grep -lir 'string' ~/directory/*` destination/

Повернення застарілих; використовуйте замість цього більш портативний, читабельний і складний $ (...).
користувач невідомий

2

Використовуючи лише визначені POSIX функції та не допускаючи припущень щодо імен файлів:

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

Примітки:

Ви сказали "string" не "pattern", тому -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"/ зовнішній /

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.