web-dev-qa-db-ja.com

find -exec内のパイプコマンド

すべての.txtファイルを検索して、いくつかの文字列を検索するとします。私はします:

find ./ -type f -name "*.txt" -exec egrep -iH 'something' '{}' \;

次のように、より複雑なフィルタリングを行う場合はどうなりますか。

egrep something file.txt | egrep somethingelse | egrep other

Find -execの内部? (または類似)

必要なときに簡単に入力できる解決策を探していることを覚えておいてください。これはシェルスクリプトを使用して数行で実行できることを知っていますが、それは私が探しているものではありません。

4
1nt3rn3t

Find内から実行する必要がある場合は、シェルを呼び出す必要があります。

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
11
terdon

編集:この答えは推奨されませんですが、bashスクリプトでの潜在的に危険な落とし穴の比較と説明のためにここに残されています。


bash(または別のシェル)を-execコマンド:

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
1
trobinson