1. ホーム
  2. linux

[解決済み】linuxのfind -execコマンドにパイプ|を含めるには?

2022-04-01 21:04:06

質問

これはうまくいきません。 これはfindでできるのでしょうか? それともxargsが必要ですか?

find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;

解決方法は?

パイプ記号を複数のプロセスを実行する命令として解釈し、あるプロセスの出力を別のプロセスの入力にパイプする仕事は、シェル(/bin/shまたは同等のもの)が担当します。

この例では、トップレベルのシェルを使って、次のようにパイピングを実行することができます。

find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'

効率的には、findを1回、zcatを多数回、agrepを1回呼び出すという結果になります。

この場合、zcatの多数の呼び出しによって生成されたすべての出力を処理するagrepプロセスが1つだけ生成されることになります。

何らかの理由でagrepを複数回起動したい場合は、そのようにします。

find . -name 'file_*' -follow -type f \
    -printf "zcat %p | agrep -dEOE 'grep'\n" | sh

これは、実行するコマンドのリストをパイプを使って構築し、それらを新しいシェルに送信して実際に実行させるものです。 (最後の "| sh" を省略することは、このようなコマンドラインのデバッグやドライランを行うのによい方法です)。

効率という点では、findの1回の起動、shの1回の起動、zcatの多数回の起動、agrepの多数回の起動を要することになります。

コマンドの起動回数の点で最も効率的なのは、Paul Tomblin氏の提案である。

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

...これは、findの1回の呼び出し、xargsの1回の呼び出し、zcatの数回の呼び出し、agrepの1回の呼び出しにかかる費用です。