Перенаправление зацикленных команд grep в отдельные файлы

Перенаправление зацикленных команд grep в отдельные файлы

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

Я сделал попытку (используяэтот вопросв качестве руководства) и придумал:

#!/bin/bash

mkdir -p grep_results   # For storing results

echo "Performing grep searches.."
while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "Seaching for $line.."
    grep -r "$line" --exclude-dir=grep_results . > ./grep_results/"$line"_infile.txt
done

echo "Done."

Однако при запуске консоль зависает, пока я не нажму CTRL-C:

$ bash grep_search.sh search_terms.txt
Performing grep searches..

В чем проблема этого скрипта? Или я неправильно подхожу?

решение1

Здесь есть несколько проблем:

  1. Цикл whileне считывает никаких входных данных. Правильный формат:

    while read line; do ... ; done < input file
    

    Или

    some other command | while read ...
    

    Ваш цикл, таким образом, зависает, ожидая ввода. Вы можете проверить это, запустив свой скрипт, а затем набрав что-нибудь и нажав Enter (здесь я ввел foo):

    $ foo.sh 
    Performing grep searches..
    foo
    Searching for foo..
    

    Вы можете улучшить это, добавив подсказку в свой read:

    while IFS='' read -p "Enter a search pattern: " -r line ...
    

    Но он будет работать до тех пор, пока вы не остановите его с помощью Ctrl+ C.

  2. ( что || [[ -n "$line" ]]означает "ИЛИ переменная $line не пуста") никогда не выполняется. Поскольку readзависает, "ИЛИ" никогда не достигается. Я вообще не понимаю, что вы хотели, чтобы он делал. Если вы хотите найти, $lineесли $lineопределено, и использовать read, если нет, вам понадобится что-то вроде:

    if [[ -n "$line" ]]; then
         grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
    else
        while IFS='' read -p "Enter a search pattern: " -r line || [[ -n "$line" ]]; do
          grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
        done
    fi
    

    Здесь, если $lineне определено, вам все равно нужно ввести его вручную. Более чистый подход — либо передать файл в whileцикл:

    while IFS='' read -r line || [[ -n "$line" ]]; do
      grep -r "$line" --exclude-dir=grep_results > ./grep_results/"$line"_infile.txt
    done < list_of_patterns.txt
    

Связанный контент