web-dev-qa-db-ja.com

bash-私にできること:find .... -exec this && that?

find-execで呼び出される2つのシェルコマンドを論理的に組み合わせる方法はありますか?

たとえば、文字列fooとその出現を含むすべての。csvファイルを出力するには、次のようにします。

find . -iname \*.csv -exec grep foo {} && echo {} \;

しかしbashは、「-execへの引数がありません」というメッセージを表示します

26

-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 {} +
26

直面している問題は、シェルが最初にコマンドラインを解析し、&&演算子で区切られた2つの単純なコマンドfind . -iname \*.csv -exec grep foo {}echo {} \;を確認することです。 &&find . -iname \*.csv -exec grep foo {} '&&' echo {} \;)を引用するとバイパスされますが、findによって実行されるコマンドは、grepのようになり、引数foowibble.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 {} \;

grepechoは、単に-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 {}" \;

3