find-execで呼び出される2つのシェルコマンドを論理的に組み合わせる方法はありますか?
たとえば、文字列fooとその出現を含むすべての。csvファイルを出力するには、次のようにします。
find . -iname \*.csv -exec grep foo {} && echo {} \;
しかしbashは、「-execへの引数がありません」というメッセージを表示します
-exec
は、(シェルではなく)コマンドを実行し、コマンドの結果(ゼロまたはゼロ以外)に基づいてtrueまたはfalseと評価される述語です。終了ステータス)。
そう:
find . -iname '*.csv' -exec grep foo {} \; -print
だろうprintgrep
がファイル内でfooを見つけた場合のファイルパス。 -print
の代わりに、別の-exec
述語またはその他の述語を使用できます
find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;
否定については!
および-o
検索演算子も参照してくださいor。
または、次のようにシェルを起動できます。
find . -iname '*.csv' -exec sh -c '
grep foo "$1" && echo "$1"' sh {} \;
または、すべてのファイルに対してシェルを起動する必要を回避するには:
find . -iname '*.csv' -exec sh -c '
for i do
grep foo "$i" && echo "$i"
done' sh {} +
直面している問題は、シェルが最初にコマンドラインを解析し、&&
演算子で区切られた2つの単純なコマンドfind . -iname \*.csv -exec grep foo {}
とecho {} \;
を確認することです。 &&
(find . -iname \*.csv -exec grep foo {} '&&' echo {} \;
)を引用するとバイパスされますが、find
によって実行されるコマンドは、grep
のようになり、引数foo
、wibble.csv
、&&
、echo
およびwibble.csv
。 &&
演算子を解釈するシェルを実行するようにfind
に指示する必要があります。
find . -iname \*.csv -exec sh -c 'grep foo "$0" && echo "$0"' {} \;
sh -c SOMECOMMAND
の後の最初の引数は$0
であり、$1
ではないことに注意してください。
コマンド呼び出しを-exec … +
でグループ化することにより、すべてのファイルのシェルプロセスの起動時間を節約できます。処理を容易にするために、$0
がファイル名を列挙できるように、いくつかのダミー値を"$@"
として渡します。
find . -iname \*.csv -exec sh -c 'for x in "$@"; do grep foo "$x" && echo "$x"; done' \ {} +
シェルコマンドが&&
で区切られた2つのプログラムである場合、find
はそれ自体でジョブを実行できます。2つの連続する-exec
アクションを書き込み、2番目のアクションは最初のアクションのみが実行されます1つはステータス0で終了します。
find . -iname \*.csv -exec grep foo {} \; -exec echo {} \;
(grep
とecho
は、単に-exec echo
を-print
に置き換えることができ、結果の出力は特に有用ではないので、単に説明のためのものであると思います。)
この特定のケースでは、私はそうします:
find . -iname \*.csv -exec grep -l foo \{\} \;
または ack がある場合:
ack -al -G '.*\.csv' foo
あなたの実際の質問に答えるために、このようなものがうまくいくかもしれません:
find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;