web-dev-qa-db-ja.com

Bash:ファイルのディレクトリで特定の文字列を検索する方法はありますか?

可能な重複:
linuxでテキストパターンを検索します

Bashでは、探している特定の文字列が現在のディレクトリにあるファイル内に存在するかどうかを知らせるコマンドがあるかどうか疑問に思いました。

現在のディレクトリのCファイルのセット内で関数 'toUpperCase()'を探しているとします。たくさんのファイルがあるので、vimを使って手動でそれぞれを開き、文字列 'toUpperCase'をチェックするのは時間がかかるのでしたくないでしょう。 bashコマンドラインではない場合、これを効率的に実行する別の方法はありますか?

41
Dark Templar

grepの場合:

grep -R "toUppercase()" *

あるいは、 ack-grep がインストールされているのなら、単に:

ack-grep "toUppercase"

ack-grepを使用して、Cファイル内の検索を制限したい場合は、

ack-grep -cc "toUppercase()"

ack-grepはOSXにもインストールできますが、実行ファイルは単にackと呼ばれます。

60

標準のテキスト検索ツールは grep です。

現在のディレクトリ内のすべてのtoUpperCase(ファイルで文字列.cを探すには、次のようにします。

grep -F 'toUpperCase(' *.c

サブディレクトリも調べたい場合は、

grep -r --include='*.c' -F 'toUpperCase('

Cの関数呼び出しを探しているなら、 ctags が適しています。すべてのソースファイルに対して1回実行して識別子のインデックスを作成し、次にエディタを使用して呼び出し間を移動します。すべてのvi風エディタはctagsのTAGSファイルを使用できます。 Emacsを使用している場合は、同様のプログラムetagsを実行してください。

10
Gilles

Vimを使用しています。これを行うためのツールが組み込まれています。

予想通り、grepを使用するように言っている7つの答えがあります。しかし、あなたがあなたの質問からvimを使用していることに気づいたのは、これまでのところ私だけです。そのため、cangrep内からvimを使用しますが、alsovimの組み込みツールを使用できます。これは:vimgrepコマンドを介して呼び出されます。

「現在のディレクトリにあるすべてのCソースファイルから関数toUpperCase()への呼び出しを検索するには」vimコマンドを入力します。

:vimgrep "\<toUpperCase\_s*(" *.c

結果の一致リストは、quickfixリストに自動的にロードされ、次のいずれかでアクセスできます(微妙な違いについてはオンラインヘルプを参照してください)

:copen
:cwin

関数を見つけるためにdefinitionを呼び出すのではなく、ctagsがツールです。 Gillesのanswer で説明されているように、:tjumpまたは:tselectコマンドと組み合わせて。

:vimgrepを使用する理由

オンラインヘルプ(:help grep)にはいくつかの理由がありますが、ここでは説明しません。さらに、:vimgrepのアクションを dietbuddhaのanswer のアクションと比較します。 dietbuddhaのコマンドラインは、個々のCソースファイルごとに個々のgrepプロセスをフォークします。そのオーバーヘッドを削減するためにxargsも使用していません。そして、出力が終了したら、何らかの方法で出力を解析して、関連するソースファイルでテキストエディターを呼び出す必要があります。 :vimgrepは複数の追加プロセスを分岐しません。結果を使用すること自体が単純です。結果のクイックフィックスリストのエントリの1つを選択するだけで、関連するソースファイルの関連する行にカーソルが自動的に配置されます。

実際、それはあなたが書いたものをあなたが手で行うことを正確に行いますが、自動的に行われます。これは、テキストエディターのアクションを自動化する方法です。手動でロードされたかのようにファイルをロードし、正規表現を検索し(vimの別の場所で既に使用しているsame正規表現構文を使用)、一致する場所を記録します。ファイルをアンロードします。

6
JdeBP

はい、ツールは grep と呼ばれます。

Grepコマンドは、指定されたパターンに一致する行を含む1つ以上の入力ファイルを検索します。デフォルトでは、grepは一致する行を表示します。

基本的な使い方は:

grep something somewhere

具体的には、

grep [some options] pattern file

非常に単純なケースでは、すべてのファイルを再帰的に検索したいので、-rオプションを指定します。大文字と小文字を区別しない場合は、-iオプションを使用して大文字と小文字を区別しないようにしてください。

grep -ri "touppercase()" .

一致する部分だけが必要な場合は、-oオプションを使用してください。

Grepは 正規表現 を使うことができ、 巨大なマニュアル を持っています。

3
slhck

grepが標準的な答えです。再帰的に、またはfindと組み合わせて-rフラグを使用する( this one のように、このサイトの他の質問の説明と例)

最近の私の選択はackです。おそらくあなたのコンピュータにインストールされているわけではありませんが、Ubuntuのapt-getを使ってインストールすることも、単にダウンロードすることもできます。リンク、手順、およびgrepより優れている理由は、 http://betterthangrep.com/ で入手できます。

2
Doug Harris

findgrep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

なぜgrepだけではないのですか?

grep -r string .は、現在のディレクトリ内のすべてのファイルを再帰的に処理します。もしあなたがオブジェクトファイルや他のバイナリを持っているのなら、バイナリの結果(別名)と一致するかもしれません。ジャンク。あなたがサブディレクトリにfifosやデバイスファイルを持っているのであれば、あなたは未知の/意図しない結果を招く可能性があります。

grep string *.cは現在のディレクトリの.cファイルのみを検索します。

grep string **/*.cはすべてのサブディレクトリを検索します。しかし、非常に多数の.cファイルがある場合、Shell globの最大拡張数を超える危険性があります。展開も最初に行わなければならず、それはgrepが始まる前に完全な木のトラバースを意味します。

1
dietbuddha

Grepはうまくいくでしょうが、ファイルの名前と参照されている正確な行を見つけるために、もう少しスクリプトを追加することをお勧めします。それがあなたが望むものであるならば、私は以下がうまくいくと思います。シェルスクリプトとして保存しておき、最初のコマンドラインオプションとして必要な値を渡します。

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
0
Tim Brigham

「現在のディレクトリにあるファイル内に特定の文字列が存在するかどうかはどうすればわかりますか」という特定の質問に誰も答えていないのは興味深いことです。私が知っている限りでは、ファイルグループ内で一致が見つかったかどうかだけを返すgrepオプションはありません。最も近いオプションは、ファイル名を一覧表示するための-lです。これまでのところ最も近い答えはtimからのもので、若干の微調整があります。

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

あなたは、あまり問題なくファイル拡張子のための第二引数を受け入れることによって、このシェルスクリプトをより一般的にすることができます。

ダグ

0
SnoopDougieDoug