it-swarm-ja.com

findを使用するときに複数のコマンドを実行するにはどうすればよいですか?

見つけたものに対して複数のコマンドを実行しようとしていますが、どうすればこれを達成できますか?

find . -exec cmd1; cmd2

動作していないようです。代わりに、すべてのファイルでcmd1が実行された後にcmd2を実行します。

58
Tamara Wijsman

このデモでは、最初のsh -c 'echo first; false'-exec(またはtrue)を使用します。これにより、いくつかの出力が表示され、選択した終了コードの効果も得られます。次に、echo secondが2番目のものに使用されます。現在のディレクトリに1つのファイルがあると仮定します。

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

このタイプの実際のコマンドは次のようになります。

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

2番目のセットでは、エスケープされた括弧が2つの-exec句をグループ化しています。それらの間の-falseはテスト状態を「false」に強制し、-o-execのために次の式(2番目の-false)が評価されるようにします。

man findから:

expr1 expr2
行内の2つの式は、暗黙の「and」で結合されていると解釈されます。 expr1がfalseの場合、expr2は評価されません。

expr1 -a expr2
expr1 expr2と同じ。

expr1 -o expr2
または; expr1がtrueの場合、expr2は評価されません。

エラーコード0が原因でcmd1がcmd2の実行を妨げることが問題にならない場合:

find . -exec cmd1 \; -exec cmd2 \;

両方のコマンドで常にこれを実行する唯一の信頼できる方法は、findにシェルを呼び出して、その後コマンドを順番に実行することです。

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

Cmd1とcmd2を実行するスクリプトを作成してもかまわない場合は、次のようになります。

find . -exec myscript {} \;

または

find . -exec myscript {} +

使用する \;または+ myscriptが一度に複数のファイルを処理できるかどうかに応じて(ファイル名にスペースが含まれていると、毛むくじゃらになります)。

私の経験では、あなたがスクリプトで何をしていたかは、ほとんど常に価値がありました。一度やらなければならない場合は、もう一度やり直す必要があります。

しかし、きちんとしたトリックはfind insideスクリプトを置くことです:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

その後、myscriptは、引数として指定したすべてのファイルに対して機能しますが、引数を指定しない場合は、現在のディレクトリからfindを実行し、見つかったファイルに対して自分自身を呼び出します。これは、find -execが、スクリプトで定義したシェル関数を呼び出せないという事実を回避します。

2
mza

私は多くの幸運なしに以前の両方の解決策を試みてきました。これは私にとってうまくいきました:

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
0
user9869932