Эффективная фильтрация многих файлов по их содержимому с помощью awk / sed / grep

Я хочу перечислить все файлы в каталоге (рекурсивно), которые имеют свои второй строки, полностью соответствующие определенному регулярному выражению. Общее количество файлов составляет около 60K.

До сих пор я написал эту команду: find /path -type f | xargs --no-run-if-empty -n1000 awk 'FNR = 2 && $0 ~ /^regular expression$/ {print FILENAME; nextfile}' find /path -type f | xargs --no-run-if-empty -n1000 awk 'FNR = 2 && $0 ~ /^regular expression$/ {print FILENAME; nextfile}' find /path -type f | xargs --no-run-if-empty -n1000 awk 'FNR = 2 && $0 ~ /^regular expression$/ {print FILENAME; nextfile}' .

Может ли он быть более эффективным?

Сначала остерегайтесь, что вы ошибочно использовали = вместо правильного == .

Вам не нужны xargs , вы можете запускать прямо из find . Также, как ваш awk должен выйти, как только он обработает строку 2 вместо чтения всего файла.

 find /path -type f -exec awk 'FNR == 2 && /^regular expression$/ {print FILENAME}; FNR == 2 {nextfile}' '{}' + 

Символ + в конце аргумента -exec указывает, find нужно поместить столько аргументов имени файла, сколько возможно. À-la xargs . См. find документации.

Важным моментом здесь является FNR==2 {nextfile} .

Является ли -exec лучше, чем xargs (но использование -print0 & -0 если доступно), подлежит обсуждению. С одной стороны find … | xargs … find … | xargs … позволяет немного распараллеливать с find чтения еще нескольких имен файлов, в то время как awk проверяет предыдущую партию. С другой стороны, распараллеливание может привести к деструкции диска с awk и find конкуренцию для разных дорожек диска. Ваше оборудование (размер кеша, SSD и т. Д.) Изменит сделку. Затем профиль решает.

Вы можете попробовать:

 grep -n <reg expr> /path/to/* | grep ":2:" | cut -d ':' -f1 

Пока :2: не является частью <reg expr> .

Существует также -x для полного соответствия строк.

Не знаю, если это быстрее – у меня нет 60k файлов для тестирования с помощью:]