web-dev-qa-db-ja.com

組み合わせたコマンドを「find -exec」に渡すにはどうすればよいですか?

-execオプションを使用して結合されたコマンドをfindに渡すための有効な構文は何ですか?


例:

find . -type f -name "*.txt" -exec grep FirstKeyWord {} | grep SecondKeyWord \;

次のエラーメッセージで失敗します。

find: grep: missing argument to `-exec`
;: No such file or directory

&&ではなく;または|を使用してコマンドを組み合わせると、同じ種類の障害が発生します。 'または$()または{}などで結合されたコマンドを引用してみましたが、(無残に)失敗しました。

注:カスタムスクリプトを使用せずに、ワンライナーソリューションを探しています。

4
Bludzee

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' \;
8
Eric

あなたの具体的な例として、これを行うことができます:

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 {} \;
2
J Earls

「-exec」を使用すると、多くのサブプロセスが作成されるため、お勧めしません。

「xargs」で「find」を使用することを検討してください(「-print0」と「-0」を使用)

find . -type f -name "*.txt" -print0 | xargs -0 grep FirstKeyWord | grep SecondKeyWord

これにより、多くのファイルに対して「grep」が1回生成されます(プログラムが持つことができる引数の数の上限まで)。

0
Vouze