foo
というプログラムがあり、findで見つかった結果ごとに実行したいと思います。だからこのようなもの:
find . -name '*.o' -type f -exec foo {} \;
特定の文字列バーに対するfoo
のこれらすべての呼び出しの出力をgrepしたいと思います。だから私はこれを追加します:
find . -name '*.o' -type f -exec foo {} \; | grep bar
しかし、一致がどのファイルから来ているかについての元の情報を失います。 find
コマンドに-fprintf /dev/stderr '%p\n'
を追加しようとしましたが、grepの結果が出力されないため、stdoutがなくなったように見えます。
各ファイル名を出力に出力して、そのファイルに対応するgrep結果を後で印刷するにはどうすればよいですか?
あるいは、grep
の-H
引数を機能させる方法があれば、それでも問題ありませんが、書かれているように、stdinからテキストを渡すだけで、grep
がファイル名。 xargs
のさまざまな呪文を試しましたが、どれも機能しませんでした。
各ファイル名を出力に出力し、その後にそのファイルに対応するgrep結果を出力するには、-exec foo {} | grep
パイプをシェルでラップできます。
find . -name '*.o' -type f -print -exec sh -c 'foo "$1" | grep "bar"' sh {} \;
Grepの-H
引数を標準入力で機能させるには、ご使用のバージョンのgrep
が--label=
オプションをサポートしている場合に実行できます。
find . -name '*.o' -type f -exec sh -c '
foo "$1" | grep -H --label="$1" "bar"
' sh {} \;
または(検索結果が+
の代わりに\;
マルチ引数をサポートしている場合):
find . -name '*.o' -type f -exec sh -c '
for f; do foo "$f" | grep -H --label="$f" "bar"; done
' sh {} +
これはかなり醜いですが、それはあなたのために働くでしょう:
find . -name '*.o' -type f -exec sh -c 'foo "$1" | sed "s@^@$1\t@"' _ {} \;
これにより、各行の先頭にファイル名とタブが配置されます。裸の下線は、生成されたシェルの$0
に入力され、ファイル名を$1
のままにする文字列です。これで、findの出力をgrepでき、ファイル名が出力に表示されます。
これは、@
文字を含むファイル名では機能しません。それが懸念される場合は、シェルスクリプトを拡張できます。
find . -name '*.o' -type f -exec sh -c '
r=$(echo "$1" | sed "s/@/\\\\\\\\@/g")
foo "$1" | sed "s@^@$r\t@"
' _ {} \;
8つのバックスラッシュは試行錯誤によって決定されました...
または、便利な「検索と置換」パラメーター置換があるbash(またはksh)を使用する
find . -name '*.o' -type f -exec ksh -c 'foo "$1" | sed "s@^@${1//@/\\\\@}\t@"' _ {} \;
各ファイル名を出力に出力して、そのファイルに対応するgrep結果を後で印刷するにはどうすればよいですか?
1。) grepの2つのインスタンスを使用します。1つはファイル名の印刷用で、もう1つは一致の印刷用です。
find . -name '*.o' -type f -exec grep -l bar {} \; -exec grep bar {} \;
2。) grepを複数のファイルであるかのように動作させます:
find . -name '*.o' -type f -exec grep bar {} /dev/null \;
これでは、例のように[..]-exec foo {} \;[...]
とパイプ内でgrepを実行する場合の問題は解決されません。