ディレクトリとすべてのサブディレクトリで、自分の名前を含むすべてのテキストファイルを見つける必要があります。どうすればいいですか? (好ましくはawkコマンドなし)
ベストアンサー1
移植性を最大化し、ファイル名にスペースやその他の文字を含めることができる場合、およびIFS
内部引用符を処理しないシステムで機能するには、次のようにします。find
{}
find -exec
結合するそしてsh
一般パラメータ渡し:
find DIRECTORY -type f -exec sh -c 'grep -lFe "$(basename "$1")" "$1"' sh {} ';'
find DIRECTORY -type f
すべての一般ファイルを再帰的に列挙しますDIRECTORY
。-exec ... ';'
見つかったファイルごとにコマンドを実行します。コアはsh
to コマンドで行われます{}
。ここで:
- 次のコマンドを使用して標準シェルを実行します。スクリプト
grep -lFe "$(basename "$1")" "$1"
一致する各ファイルのコマンド文字列。ここで: - そして、2つのパラメータを
sh
「sh
」とに渡します{}
。sh
インラインスクリプト$0
(エラー報告用のシェルなどの実行中のプログラムの名前)に使用されます。一致するファイル名のみで構成された引数は置き換えられるため、find
スクリプト自体は完全なファイルパスを 。{}
sh
$1
これはすべてのPOSIX互換システムで機能します。{}
引用符付き文字列内で使用find -exec
実装によって定義された動作がありますgrep
したがって、移植性がなく(GNUとほとんどのBSDがサポートしていますが)、ファイル名が解釈されるため危険です。シェルコードで。
任意のファイル名に、IFS
値が不明な空白、ワイルドカード、または入力フィールドの区切り文字変数を含めることができる場合は、必ず引用符を付ける必要があります。そうしないと、複数の単語に分割され、プログラムが予期しない方法で動作します。
より効率的にfind -exec
withを使用する+
と、できるだけ少ない数のシェルを実行できます。
find DIRECTORY -type f -exec sh -c 'for x in "$@" ; do grep -lFe "$(basename "$x")" "$x" ; done' sh {} '+'
これはまだ移植可能ですが、実行ごとに多くのファイルパスを提供するため、sh
多くのシェルを起動しません。シェルプログラムがありますfor
リングすべてのファイルを見てください。頻繁に実行されるタスクの場合は、;
""でコマンドを終了するよりも優れたオプションです。