最初のマッチ後に「検索」を終了する方法は?

最初のマッチ後に「検索」を終了する方法は?

私はwhileループでfindを使用しています。 ip.txtのIPリストを取得し、ファイルディレクトリからIPを検索し、見つかった各IPのファイル名をresults.resというファイルに書き込みます。

正常に検索するたびに停止し、次のIPに移動したいと思います。

私の現在のスクリプトは次のとおりです。

while read ip; do
    find . -type f -maxdepth 1 -not -name ips.txt -not -name results.res -print0  | xargs -0 grep "$ip" >> results.res
done < ips.txt

サイトで他の回答を調べたところ、以下を使用して発見しました。

-print -quit
-print | head -n 1

最初の成功した検索の後、検索を停止します。しかし、whileループを使用しているので、これはうまくいきません。誰でも可能な解決策を提案できますか?

答え1

while IFS= read -r ip; do
  find . -maxdepth 1 \
         -type f \
         ! -name ips.txt \
         ! -name results.res \
         -exec grep -lwFe "$ip" {} \; \
         -quit
done < ips.txt > results.res

ファイルの各行を変数ips.txtとして読み取り、$ip基準に一致するファイルを参照しfind(特定の順序なしで)、$ip固定F文字列とordで区切られたw最初のファイルを報告します。成功すると-quit呼び出され、次を返します-execgrep本物一致するものが見つかった場合は終了状態です。

答え2

現在のスクリプトがどのように書かれているかに応じて、を実行してから、見つかったすべてのファイルとfindgrep見つかったすべてのファイルを実行します。ipips.txt

同じファイルのリストを取得するために毎回実行する必要はないので、ループfindから取り出してwhile変数に割り当てます。また、見つかったすべてのファイルに対して実行する必要はなく、grep1つのコマンドですべてのファイルを検索できます。これでファイルのリストがあるので、grep各ファイルに対して操作を実行し、ip最初の一致のみを返すことができます。これでスクリプトは次のようになります。

files=$(find . -maxdepth 1 -type f -not -name ips.txt -not -name results.res)
while read ip; do
    grep --with-filename --max-count=1 "$ip" $files | head -n 1 >> results.res
done < ips.txt

これはgrepすべてのinコマンドのすべてのファイルを繰り返し、find各IPアドレスとそのIPアドレスが見つかった最初のファイルを含む行を置く必要があります。 ipips.txtresults.res

編集する:

いくつかのテストを行った後、古いコードはスペースや奇妙な文字を含むファイル名をまったく処理しないため、より良い方法があるようです。findここでは必要ないようですから取り除きます。

とをgrep除いて、現在のディレクトリ内のすべてのファイルを繰り返す予定なので、以下を探さなくても使用できます。results.resips.txtgrep

while read ip; do
    grep --with-filename --max-count=1 --exclude={results.res,ips.txt} "$ip" * | head -n 1 >> results.res
done < ips.txt

関連情報