ディレクトリとすべてのサブディレクトリで、自分の名前を含むすべてのテキストファイルを見つける必要があります。どうすればいいですか? (好ましくは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
リングすべてのファイルを見てください。頻繁に実行されるタスクの場合は、;
""でコマンドを終了するよりも優れたオプションです。
答え2
find directoryname -type f -exec grep -l {} {} \;
これはfind
、純粋なファイル(ディレクトリ、デバイス、シンボリックリンクなどを除く)を検索し、指定された引数をgrep
使用して見つかった各ファイルを実行するように指示します。-l
一致する行ではなくファイル名のみを表示するようにgrepに指示します。{}
ファイル名を示し、\;
コマンドを終了します。
もちろん、パスではなく、ファイル名自体を検索する必要があるという意味かもしれません。これは、最初のセクションから目次セクションを削除する必要があることを意味します{}
。 1つの解決策は次のとおりです。
find directoryname -type f -exec sh -c 'grep -l $(basename {}) {}' \;
$( .. )
各ファイルに対してパラメータ置換を実行する必要があるため、シェルが起動します。basename
目次セクションの前の部分を削除します。
一重引用符が必要です。それ以外の場合、$(..)部分はfindを介してシェルを起動するのではなく、コマンドを入力したときに評価されます。
答え3
GNUシステムでは、次のことができます。
find . -type f -printf '%f\0%p\0' | xargs -r0n2 grep -lFe
(-type f
は次のように制限されます。定期的なファイルのみ。-xtype f
一般ファイルへのシンボリックリンクも考慮するには)に変更してください。
答え4
これは私にとって効果的です。
find /path/ -type f -exec sh -c "grep -l \"\$(basename {})\" {}" \;
Explanation:
-type f
:ファイルのみ検索sh -c
:各ファイルに対してシェルを実行します。grep -l
:ファイル名のみ表示\$(basename {})
: 基本名を取得するには grep