すべての.txt
ファイルを検索し、文字列を検索するとします。次のようにします。
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
次のような、より複雑なフィルタリングを実行したい場合はどうすればよいですか:
egrep something file.txt | egrep somethingelse | egrep other
Inside find -exec?(または同様のもの)
必要なときに簡単に入力できるソリューションを探していることに注意してください。これはシェルスクリプトを使用して数行で実行できることは知っていますが、それは私が探しているものではありません。
回答
検索内から実行する必要がある場合は、シェルを呼び出す必要があります。
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
他の方法としては、代わりにxargs
を使用する方法があります:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
または、任意のファイル名に対してはるかに安全です(find
が-print0
をサポートしていると仮定します):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
または、代わりにシェルループを使用することもできます:
find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done
コメント
回答
編集:この回答は推奨されませんですが、潜在的に危険な落とし穴の比較と説明のためにここに残されていますbashスクリプトで。
-exec
コマンドとしてbash
(または別のシェル)を配置できます。
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
この方法で行うことの欠点の1つは、より多くの情報を作成できることです。コマンドがより複雑になると、ネストされた引用符の問題が発生する可能性があります。これを回避したい場合は、for
ループに分割できます:
for i in $(find -type -f -name "*.txt"); do if egrep -iH something "$i" | egrep somethingelse | egrep other; then echo "Found something: $i" fi done
コメント
- 最初のものはまさに私が探していたものです。非常にシンプルで、ニーズに応じて入力できるほど小さいです。ありがとう。
- その
for
ループは非常に悪い考えです。 bashの落とし穴#1としても知られています。 - 最初のコマンドのこの
"{}"
は、コードインジェクションにつながる可能性さえあります。私からファイルを受け取ったと想像してみてください。'文字通り" & rm -rf ~ & : ".txt
という名前のファイルがあります。幸いなことに、-type -f
は無効であり、ホームディレクトリを保存しただけです。タイプミスを修正して、再試行してください。 🙂 terdonはそれを正しく行いました:find … -exec sh -c '… "$1" …' foo {} \;
。 - 情報をありがとう!ええ、
-type -f
は、find
を使用するときに常にタイプミスですが、'私の答えでは気づかない。おっと。 terdon 'の答えの方が優れていますが、比較のために'これを残しておきます。 - @terdon:tx mywiki.wooledge.orgページを参照してください。 '多数のGPが1か所にきちんとまとめられているのは素晴らしいことです。
xargs
は、必要に応じてxargs -I {} sh -c '...' sh {}
として使用することもできます(必要に応じて、-P
を使用して並列ジョブを実行できます。