自分の名前を含むテキストファイル

自分の名前を含むテキストファイル

ディレクトリとすべてのサブディレクトリで、自分の名前を含むすべてのテキストファイルを見つける必要があります。どうすればいいですか? (好ましくは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 ... ';'見つかったファイルごとにコマンドを実行します。コアはshto コマンドで行われます{}。ここで:

  • 次のコマンドを使用して標準シェルを実行します。スクリプトgrep -lFe "$(basename "$1")" "$1"一致する各ファイルのコマンド文字列。ここで:
    • $1一致するファイル()のデフォルトのファイル名を見つけるには、次のコマンドを使用します。コマンドの置き換えそして基本名- スペースやワイルドカードを含めることができる場合を説明するために、コマンドの置き換えと変数が引用されます。
    • grepこのデフォルト名の一致ファイル(まだ " $1")は、-l一致するファイルの名前のみを印刷するために使用されます。"$1"スペースまたはワイルドカード文字を解決するには、再引用してください。
  • そして、2つのパラメータをshsh」とに渡します{}shインラインスクリプト$0(エラー報告用のシェルなどの実行中のプログラムの名前)に使用されます。一致するファイル名のみで構成された引数は置き換えられるため、findスクリプト自体は完全なファイルパスを 。{}sh$1

これはすべてのPOSIX互換システムで機能します。{}引用符付き文字列内で使用find -exec 実装によって定義された動作がありますgrepしたがって、移植性がなく(GNUとほとんどのBSDがサポートしていますが)、ファイル名が解釈されるため危険です。シェルコードで

任意のファイル名に、IFS値が不明な空白、ワイルドカード、または入力フィールドの区切り文字変数を含めることができる場合は、必ず引用符を付ける必要があります。そうしないと、複数の単語に分割され、プログラムが予期しない方法で動作します。


より効率的にfind -execwithを使用する+と、できるだけ少ない数のシェルを実行できます。

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

関連情報