Как вы решаете проблему «Слишком много файлов» при работе в Bash? - PullRequest
6 голосов
/ 09 октября 2008

Мне много раз приходилось работать с каталогами, содержащими сотни тысяч файлов, выполнять сопоставление текста, замену и так далее. Если я иду по стандартному маршруту, скажем

grep foo *

Я получаю сообщение об ошибке "слишком много файлов", поэтому я в итоге

for i in *; do grep foo $i; done

или

find ../path/ | xargs -I{} grep foo "{}"

Но они не оптимальны (создайте новый процесс grep для каждого файла).

Это похоже на большее ограничение в размере аргументов, которые могут получать программы, потому что * в цикле for работает нормально. Но в любом случае, как правильно справиться с этим?

PS: не говорите мне вместо этого делать grep -r, я знаю об этом, я думаю об инструментах, у которых нет рекурсивной опции.

Ответы [ 5 ]

8 голосов
/ 10 октября 2008

В более новых версиях findutils find может выполнять работу xargs (включая поведение glomming, при котором используется только столько процессов grep, сколько необходимо):

find ../path -exec grep foo '{}' +

Использование + вместо ; в качестве последнего аргумента вызывает такое поведение.

6 голосов
/ 09 октября 2008

Если существует риск, что имена файлов содержат пробелы, не забудьте использовать флаг -print0 для поиска вместе с флагом -0 для xargs:

find . -print0 | xargs -0 grep -H foo
4 голосов
/ 09 октября 2008

xargs не запускает новый процесс для каждого файла. Это связывает воедино аргументы. Посмотрите на параметр -n для xargs - он контролирует количество аргументов, передаваемых каждому выполнению подкоманды.

0 голосов
/ 10 октября 2008

Ну, у меня были те же проблемы, но, кажется, все, что я придумал, уже упоминалось. В основном было две проблемы. Выполнение глобусов стоит дорого, выполнение ls в каталоге с миллионами файлов занимает вечно (20+ минут на одном из моих серверов), а выполнение ls * в каталоге с миллионами файлов занимает вечно и приводит к ошибке «список аргументов слишком длинный»

find /some -type f -exec some command {} \; 

, кажется, помогает с обеими проблемами. Кроме того, если вам нужно выполнить более сложные операции с этими файлами, вы можете написать сценарий в несколько потоков. Вот Python учебник для сценариев CLI. http://www.ibm.com/developerworks/aix/library/au-pythocli/?ca=dgr-lnxw06pythonunixtool&S_TACT=105AGX59&S_CMP=GR

0 голосов
/ 09 октября 2008

Я не вижу этого

for i in *; do
    grep foo $i
done

будет работать, так как я думал, что «слишком много файлов» является ограничением оболочки, следовательно, он также не будет работать для цикла for.

Сказав это, я всегда позволяю xargs выполнить основную работу по разделению списка аргументов на управляемые биты таким образом:

find ../path/ | xargs grep foo

Процесс запускается не для файла, а для группы файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...