Bash сканировать миллионы файлов и быстро проверять значение

80
8

У меня есть миллионы файлов в папке (вложенной). Мне нужно отсканировать значение из этих файлов и напечатать строки, содержащие это значение (скажем LINE_TXT). Раньше я использовал sed для каждого файла, но для этого потребовалось 45 минут. Мое предыдущее решение было примерно таким:


FILES=$(find $1 -type f -name 'filename.txt')
for f in $FILES
do
if [[ "$LINE" == *LINE_TXT* ]]; then
echo $LINE
fi
done

Я понял, что pipemill - лучший способ добиться этого. Мое основное решение - это что-то вроде этого:


makefifo mypipe
find $1 -type f -name 'filename.txt' | xargs cat > my pipe &
while read -r LINE
do
if [[ "$LINE" == *LINE_TXT* ]]; then
echo $LINE
fi
done << mypipe

Время работы 1 мин. Могу ли я улучшить это дальше?

спросил(а) 2012-12-02T17:06:00+04:00 7 лет, 9 месяцев назад
1
Решение
97

Мне кажется, что накладные расходы script будут быстрее.


fgrep -r -h 'LINE_TXT' $1

Просто позвольте grep выполнить собственную рекурсию через ваши каталоги с помощью -r. И если вы не хотите, чтобы его вывод включал имя файла в его вывод, включите опцию -h. Вы можете передавать свой результат через все, что вам нужно для последующей обработки.


Если вы хотите искать только для определенных имен файлов, опция grep -r имеет собственные опции: --include и --exclude, упомянутые на ее странице руководства. Например:

fgrep -h -r --include '*/filename.txt' 'LINE_TXT' $1

В то время как команда find превосходна и неоценима в определенных ситуациях, если вы можете использовать параметры, встроенные в один инструмент, например grep, вы несете дополнительные накладные расходы. Команда find не просматривает файлы, поэтому для каждого из них все равно придется запускать grep. Если вы хотите использовать find, это может выглядеть примерно так:


find $1 -name 'filename.txt' -exec fgrep 'LINE_EXT' {} \;

Это дает вам доступ к возможностям поиска каталогов find, но если все, что вы хотите сделать, это поиск особо имени файла в дереве вашего каталога, grep -r --include, вероятно, достаточен и обязательно будет запускаться быстрее.

ответил(а) 2012-12-02T17:15:00+04:00 7 лет, 9 месяцев назад
57

Да, find $1 -type f -name 'filename.txt' | xargs fgrep LINE_TXT, если вы хотите найти все совпадения "LINE_TXT" в любом из этих файлов.

ответил(а) 2012-12-02T17:09:00+04:00 7 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема