Как я рекурсивно grep первых 50 строк каждого файла в каталоге?

10

Мне нужно искать первые 50 строк каждого файла в каталоге и его подкаталогах.

Это сделает рекурсивную часть, но как ограничить только первые 50 строк каждого файла?

grep -r "matching string here" .

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

zevlag
источник
Вы хотите просто знать файлы, которые соответствуют, или вы хотите иметь только соответствующую строку, или вы хотите, чтобы соответствующая строка вместе с именем файла?
gniourf_gniourf

Ответы:

11
  • Если вы просто хотите файлы, которые соответствуют:

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
    

    или

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
    
  • Если вы хотите только соответствующие строки:

    find . -type f -exec head -n 50 {} \; | grep "matching string here"
    

    или лучше,

    find . -type f -exec head -q -n 50 {} + | grep "matching string here"
    
  • И если вы хотите оба:

    find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
    

Замечания.

  • Может быть немного проще, sedа не комбо head- grep.
  • Позвольте мне подчеркнуть, что все три метода на 100% безопасны в отношении имен файлов, которые могут содержать забавные символы (пробелы, новые строки и т. Д.).
  • В двух из этих методов я предполагаю, что у вас есть достаточно свежая версия bash.
  • Вы можете использовать -exec ... +в каждом методе, но тогда вам придется самостоятельно кодировать свой внутренний цикл! (тривиальное упражнение оставлено читателю). Это может быть немного более эффективно, если у вас есть файлы gazillion.
gniourf_gniourf
источник
4

Если вам нужен вывод grep, как в оригинале, вы можете сделать:

find . -type f | while read f; do 
  if head -n 50 "$f"|grep -s "matching string here"; then
    grep "matching string here" "$f" /dev/null 
  fi
done

Если вам нужны только имена файлов, вы можете заменить 2-й grep на echo "$f".

Майкл Зельманн
источник
1

Вам нужно будет объединить несколько разных утилит, чтобы получить желаемую функциональность. Используйте findкоманду, чтобы просмотреть каталоги, найти все файлы и выполнить headкоманду для каждого найденного файла. headКоманда может быть использована для дампа только первые 50 строк каждого файла. Наконец, направьте вывод в grep для поиска нужной вам строки.

find . -type f -exec head -n 50 {} ";" | grep "matching string here"

Собачья шерсть
источник