パターンに一致する特定のファイルでWordを見つけるにはどうすればよいですか。例えば現在のディレクトリで再帰的に見つかったCMake*
ファイルでversion
を検索しています。
ファイル名と行番号を見たい場合は、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
がシンボリックリンクをたどります。
そのバージョンはより安全で効率的ですが、移植性はありません。
find
を使用してファイルを選択し、次にgrepを使用してファイルを検索します。
find . -name "CMake*" -print0 | xargs -0 grep -F version
xargs
を使用すると、見つかったすべてのファイルに対してgrep
が開始されません。
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*
ファイルの名前のパス。
より最新のバージョンの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
Grepの検索を組み合わせて使用します。
find . -name "Cmake*" -exec grep version {} \;
この例では、現在のディレクトリから再帰的に検索し、一致するファイルに対してgrepを実行します。
find . -name "CMake*" -exec grep -H version {} \;