web-dev-qa-db-ja.com

パターンに一致する特定のファイルを検索する方法

パターンに一致する特定のファイルでWordを見つけるにはどうすればよいですか。例えば現在のディレクトリで再帰的に見つかったCMake*ファイルでversionを検索しています。

5
Meysam

ファイル名と行番号を見たい場合は、POSIXly:

find . -name 'CMake*' -type f -exec grep -nF /dev/null version {} +

(使用したくない;ここでは、ファイルごとに1つのgrepを実行します)。これは標準のGNUismに相当します。

find . -name 'CMake*' -type f -print0 | xargs -r0 grep -nHF {} +

find(最初の)、xargs(2番目の)は、渡すことができる引数の数の制限を超えずに、できるだけ多くの引数をgrepに渡します。コマンド。この分割を行うと、最後の実行でgrepに渡される引数が1つだけになる場合があり、その場合、grepはファイル名を出力しません。だからこそ/dev/nullそこ(または-H with GNU grep)。

-type f、通常のファイルのみを考慮しています(デバイス、シンボリックリンク、パイプ、ディレクトリではありません...)。

GNUismsを使用したい場合は、GNU grep機能を使用してディレクトリツリーを降りることができます。

 grep -rHnF --include='CMake*' version .

使用したくない-Rこれにより、ディレクトリツリーを降りてデバイス、fifo、ソケットから読み取るときにgrepがシンボリックリンクをたどります。

そのバージョンはより安全で効率的ですが、移植性はありません。

7

findを使用してファイルを選択し、次にgrepを使用してファイルを検索します。

find . -name "CMake*" -print0 | xargs -0 grep -F version

xargsを使用すると、見つかったすべてのファイルに対してgrepが開始されません。

3
Zelda

findの支援を必要とせずにこれを実行できることを示すためだけに。ファイルシステムを再帰するgrepの機能を利用することもできます。 grepのバージョンに-Rスイッチがあると仮定します。

$ grep -R version | awk -F: '/CMake.*:/ {print $1}'

文字列versionを含むCMake1-3という名前のファイルと、含まないCMake0という名前のファイルを含むサンプルデータをいくつか作成しました。また、文字列afileを含むversionという名前の2つのファイルも作成しました。

$ tree .
.
|-- CMake1
|-- dir1
|   |-- dirA1
|   |   `-- CMake1
|   |-- dirA2
|   `-- dirA3
|-- dir2
|   |-- dirA1
|   |   `-- CMake0
|   |-- dirA2
|   |   |-- afile
|   |   `-- CMake2
|   `-- dirA3
`-- dir3
    |-- dirA1
    |-- dirA2
    |   `-- afile
    `-- dirA3
        `-- CMake3

上記のコマンドを実行すると:

$ grep -R version | awk -F: '/CMake.*:/ {print $1}'
CMake1
dir2/dirA2/CMake2
dir3/dirA3/CMake3
dir1/dirA1/CMake1

細部

上記のコマンドは、grepから次のようなリストを生成します。

$ grep -R version 
CMake1:version
dir2/dirA2/CMake2:version
dir2/dirA2/afile:version
dir3/dirA2/afile:version
dir3/dirA3/CMake3:version
dir1/dirA1/CMake1:version

そして、awkは、CMake.*:を含むすべての文字列を検索し、これらの文字列をコロン(:)で分割し、この分割から最初のフィールドのみを返すために使用されます。対応するCMake*ファイルの名前のパス。

2グレップ+ PCRE

より最新のバージョンのgrepには、多くの場合 PCRE-Perl互換の正規表現 と呼ばれるものが含まれます。したがって、2つのgrepコマンドを使用できます。2つ目のコマンドはPCREを使用してファイルのパス部分のみを抽出し、最初のgrepから文字列の末尾の:versionビットを省略します。

$ grep -R version | grep -Po '.*CMake.*(?=:version)'
CMake1
dir2/dirA2/CMake2
dir3/dirA3/CMake3
dir1/dirA1/CMake1

-oは一致する部分のみを返しますが、-PはPCREを有効にするものです。正規表現では、末尾に(?=...)を使用して、末尾に:versionがある文字列のみを選択しています。この先読みはパターンの調整に役立つだけであり、返される結果には含まれません。また、CMake.*などの実際のパターンの一部でもありません。

行番号

最初のgrepにスイッチ-nを含めることもできます。これにより、文字列versionが検出された行番号も出力に含めることができます。

$ grep -Rn version | grep -Po '.*CMake.*(?=:version)'
CMake1:1
dir2/dirA2/CMake2:9
dir3/dirA3/CMake3:1
dir1/dirA1/CMake1:1

最初の例を機能させるには、awkコマンドを少し変更する必要があります。

$ grep -Rn version | awk -F: '/CMake.*:/ {print $1":"$2}'  
CMake1:1
dir2/dirA2/CMake2:9
dir3/dirA3/CMake3:1
dir1/dirA1/CMake1:1

最初の例では、awkを使用して行番号を別のフィールドに解析済みであるため、行番号を移動する機会が与えられます。

ここでは、番号を最初に置くことができます。

$ grep -Rn version | awk -F: '/CMake.*:/ {print $2":"$1}'  
1:CMake1
9:dir2/dirA2/CMake2
1:dir3/dirA3/CMake3
1:dir1/dirA1/CMake1
3
slm

Grepの検索を組み合わせて使用​​します。

find . -name "Cmake*" -exec grep version {} \;

この例では、現在のディレクトリから再帰的に検索し、一致するファイルに対してgrepを実行します。

1
Tim Haegele
find . -name "CMake*" -exec grep -H version {} \;
1
user17530