私は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
呼び出され、次を返します-exec
。grep
本物一致するものが見つかった場合は終了状態です。
答え2
現在のスクリプトがどのように書かれているかに応じて、を実行してから、見つかったすべてのファイルとfind
でgrep
見つかったすべてのファイルを実行します。ip
ips.txt
同じファイルのリストを取得するために毎回実行する必要はないので、ループfind
から取り出してwhile
変数に割り当てます。また、見つかったすべてのファイルに対して実行する必要はなく、grep
1つのコマンドですべてのファイルを検索できます。これでファイルのリストがあるので、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アドレスが見つかった最初のファイルを含む行を置く必要があります。 ip
ips.txt
results.res
編集する:
いくつかのテストを行った後、古いコードはスペースや奇妙な文字を含むファイル名をまったく処理しないため、より良い方法があるようです。find
ここでは必要ないようですから取り除きます。
とをgrep
除いて、現在のディレクトリ内のすべてのファイルを繰り返す予定なので、以下を探さなくても使用できます。results.res
ips.txt
grep
while read ip; do
grep --with-filename --max-count=1 --exclude={results.res,ips.txt} "$ip" * | head -n 1 >> results.res
done < ips.txt