web-dev-qa-db-ja.com

findコマンドのexecパラメーターでパイプを使用するにはどうすればよいですか?

2つの異なる実行可能ファイルを使用して、ディレクトリ内の一連のファイルを処理する検索コマンドを作成しようとしています。残念ながら、-exec findでは、パイプまたは\|は、シェルがその文字を最初に解釈するためです。

具体的には、私がやろうとしていることをここに示します(パイプがfindコマンドを終了するため動作しません):

find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print
72
hoyhoy

これを試して

find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print

別の方法として、shスクリプト内にexecステートメントを埋め込み、次に実行することもできます。

find -exec some_script {} \;
79

少し異なるアプローチは、xargsを使用することです。

find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123

私は常に少し理解しやすく、適応しやすいと感じました(空白を含むファイル名に対処するには、-print0引数と-0引数が必要です)

このmight(テストなし)は、-execを使用するよりも効果的です。ファイルのリストをxargsにパイプするため、xargsはjheadコマンドラインが長くなりすぎないようにします。

12
Palmin

-execを使用すると、任意のシェルコマンドではなく、いくつかの引数を持つ単一の実行可能ファイルのみを実行できます。これを回避するには、sh -c '<Shell command>'を使用できます。

-execの使用は非常に非効率的であることに注意してください。見つかったファイルごとに、コマンドを再度実行する必要があります。これを回避できれば、より効率的です。 (たとえば、grep-execの外側に移動するか、 Palmin で提案されているようにfindの結果をxargsにパイプすることによって。)

3
mweerden

このタイプのタスクにfindコマンドを使用することは、おそらく最良の選択肢ではありません。次のコマンドを頻繁に使用して、要求された情報を含むファイルを見つけます。

for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
3
Dimitar

これはリストを出力するので、あなたはそうしません:

find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123

または

find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123

Find -execの結果にgrepを追加します。

1
Xetius

別の方法もありますが、かなりゲットーです。

Shellオプションのextquoteを使用すると、execのものを見つけてshにパイプするために、これと同様のことができます。

root@ifrit findtest # find -type f -exec echo ls $"|" cat \;|sh
filename


root@ifrit findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh
h

少なくとも私がそれを視覚化した方法では、exec内でパイプを使用するというOPの元々の質問に近かったからです。

0
linuxgeek