Как grep тысячи файлов в каталоге для сотен строк в файле


11

Я пытаюсь составить grepзаявление, и это убивает меня. Я тоже устал от arguments list too longошибки. У меня есть файл, давайте назовем его subset.txt. Он содержит сотни строк с конкретными строками, такими как MO43312948. В моем объектном каталоге у меня есть тысячи файлов, и мне нужно скопировать все файлы, содержащие строки, перечисленные в, subset.txtв другой каталог.

Я пытался начать с этого, чтобы просто вернуть соответствующие файлы из каталога объектов.

grep -F "$(subset.txt)" /objects/*

Я продолжаю получать `bash: / bin / grep: список аргументов слишком длинный``


6
Почему вы поставили "$(subset.txt)"команду таким образом? Это подстановка команд , которая заставит вашу оболочку выполняться subset.txt (как если бы это была команда или скрипт).
JigglyNaga

Ответы:


23

Вы можете передать каталог в качестве мишени для grepс -Rи файл входных паттернов с -f:

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

Итак, вы ищете:

grep -Ff subset.txt -r objects/

Вы можете получить список подходящих файлов с:

grep -Flf subset.txt -r objects/

Итак, если ваш окончательный список не слишком длинный, вы можете просто сделать:

 mv $(grep -Flf subset.txt -r objects/) new_dir/

Если это возвращает argument list too longошибку, используйте:

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

И если ваши имена файлов могут содержать пробелы или другие странные символы, используйте (предполагая GNU grep):

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Наконец, если вы хотите исключить двоичные файлы, используйте:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

... или чтобы избежать потенциально тысяч mvвызовов с одним аргументом каждый: ... | xargs -0 mv -t bar/(при условии, что ваш mvподдерживает -tопцию).
Дэвид Фёрстер

11

использование

grep -F -f subset.txt 

сказать grep читать из subset.txtфайла.

вы можете использовать find, чтобы просмотреть файл.

find . -type f -exec grep -F -f subset.txt {} \;

или

find . -type f -exec grep -F -f subset.txt {}  +

Есть ли преимущество использования findвместо того -r, чтобы делать дополнительную фильтрацию?
phk

1
@phk grep -rищет в символических ссылках обычные файлы, что может или не может быть желательным (если они указывают на одно и то же дерево, вы ищете один и тот же файл дважды; если они указывают на внешнее, вы ищете файл, который может или не может быть быть желанным).
Жиль "ТАК - перестань быть злым"

Современные версии grepимеют опции для контроля их взаимодействия с символическими ссылками ( man grepдля определения специфики текущей системы). Рекурсив grepбудет намного быстрее, чем запускаться grepиндивидуально для каждого файла через find.
Перри

1
@ Пэрри, ты уверен в этом? Почему? Также обратите внимание, что этот ответ используется -exec +, поэтому он будет группировать файлы, а не запускать один grep на файл.
Terdon

Я исправлен, я не знал о различной семантике -exec {} +vs -exec {} \;... вы узнаете что-то новое каждый день (я до сих пор не вижу причин, по которым один рекурсив не grepбудет быстрее, чем grepзапуск нескольких s из- findза накладных расходов, связанных с созданием процесса и анализом шаблона, но я не нужно указывать конкретные цифры, подтверждающие это).
Перри

3

Если вы хотите еще больше ускорить grep, вы можете установить локаль в вашей оболочке перед ее запуском, то есть использовать «LC_ALL = c». Это будет унаследовано в grep и отключит обработку Unicode, когда в этом нет необходимости, а в некоторых случаях может значительно ускорить grep. Большой блог, документирующий это, можно найти по адресу http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Этот трюк также может ускорить сценарии оболочки bash, а не только grep.

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