-exec
オプションを使用して結合されたコマンドをfind
に渡すための有効な構文は何ですか?
例:
find . -type f -name "*.txt" -exec grep FirstKeyWord {} | grep SecondKeyWord \;
次のエラーメッセージで失敗します。
find: grep: missing argument to `-exec`
;: No such file or directory
&&
ではなく;
または|
を使用してコマンドを組み合わせると、同じ種類の障害が発生します。 'または$()または{}などで結合されたコマンドを引用してみましたが、(無残に)失敗しました。
注:カスタムスクリプトを使用せずに、ワンライナーソリューションを探しています。
Execの引数で複雑なシェルコマンドを使用して、そこでシェルを明示的に呼び出すことができます。
find . -type f -name "*.txt" -exec sh -c 'grep FirstKeyWord "$1" | grep SecondKeyWord' -- {} \;
これは、ファイルごとに指定されたコマンドリストを使用してsh
を実行し、$1
。
編集:OPはこれが機能し、より簡単であることを指摘しています:
find . -type f -name "*.txt" -exec sh -c 'grep FirstKeyWord {} | grep SecondKeyWord' \;
あなたの具体的な例として、これを行うことができます:
find . -type f -name "*.txt" -exec grep FirstKeyWord {} \; | grep "SecondKeyWord"
ところで、これは2番目のgrepを使用せずに行うこともできます。代わりに、egrep
を使用し、FirstKeyWord
の後にSecondKeyWord
を続けるか、SecondKeyWord
の後にFirstKeyWord
を続けます。
find . -type f -name "*.txt" -exec egrep "FirstKeyWord.*SecondKeyWord|SecondKeyWord.*FirstKeyWord" {} \;
find
から得られるパス名についていくつかの保証を行うことができる場合(パス名に先行スペースも内部スペースも改行もないなど)、次のようにすることもできます。
find . -type f -name "*.txt" -print | while read filename; do grep "FirstKeyWord" "${filename}" | grep "SecondKeyWord"; done
より一般的な答えは、find
から直接「できない」です。コマンドのパイピングまたは&&
または||
の使用は、シェルの機能であり、プロセスを実行する機能ではありません。
私は以前このパターンを使用しましたが、それは壊れやすく、より複雑です:
find . -type f -name "*.txt" -print \
| sed -e 's;[\\$"`!];\\&;g' \
-e 's;^.*$;grep "FirstKeyWord" "&" | grep "SecondKeyWord";' \
| sh
各ファイル名を出力し、sed
を使用してその場でシェルスクリプトに変換し(シェルの二重引用符で囲むと問題が発生する可能性があるファイル名の文字をエスケープしないように注意)、結果を実行します。シェル。
他の解決策は、処理を実行するシェルスクリプトを作成し、そのシェルスクリプトをfindから呼び出すことです。
$ cat grepit.sh
#!/bin/sh
grep "FirstKeyWord" "$1" | grep "SecondKeyWord"
$ find . -type f -name "*.txt" -exec sh grepit.sh {} \;
「-exec」を使用すると、多くのサブプロセスが作成されるため、お勧めしません。
「xargs」で「find」を使用することを検討してください(「-print0」と「-0」を使用)
find . -type f -name "*.txt" -print0 | xargs -0 grep FirstKeyWord | grep SecondKeyWord
これにより、多くのファイルに対して「grep」が1回生成されます(プログラムが持つことができる引数の数の上限まで)。