特定の文字列パターンを含まないファイルを見つけるにはどうすればよいですか?


回答:


818

grepに-L(または--files-without-match)オプションがある場合:

$ grep -L "foo" *

1
他で指摘したように、ackはデフォルトで.svn(subversion)ファイルを回避するのに役立ちます。
GuruM 2013年

11
@GuruMこれは変数をエクスポートすることでGNU grepで実行できますGREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git':^)
bufh

6
またはagを使用して同等のもの:ag -L 'foo'
ビショップ

5
魔法のように動作します!ヒント:サブディレクトリを一致させるために-rL代わりに使用-L
Ufos

1
@Larry —グロブの問題を回避するためのより明確な方法は、次のような「空の」長いオプションを使用することですgrep -L 'foo' -- *。標準では、長いオプションを取るコマンドは、--この時点以降にオプションがないことを示すために使用されます。
Paddy Landau

45

見てくださいack。これは.svn自動的に除外を行い、Perlの正規表現を提供し、単一のPerlプログラムの簡単なダウンロードです。

あなたが探しているものと同等のものは、次のようになりますack

ack -L foo

24

grepだけで(検索なしで)実行できます。

grep -riL "foo" .

これは、で使用されるパラメータの説明です grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

l(小文字)を使用すると、反対の結果になります(一致するファイル)。

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

次のコマンドは、パターンを含まないすべてのファイルを取得しますfoo

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

4
末尾のgrep 0をgrep 0 $に変更します(そうしないと、ファイル名に文字0が含まれるファイルで誤って一致します)。
clouseau 2009

9
@clouseauはほぼ正しいですがgrep '0$'、10行の倍数のファイルにも一致します。grep ':0$'最後に、行の終わりに明示的な「:0」があるかどうかを確認する必要があります。次に、一致する行がゼロのファイルのみを取得します。
TrinitronX 2011

私が使用しているUNIXには、これらのオプションを備えたfindまたはgrepのバージョンがなかったため、他のコメントで提案されている「ack」コマンドを使用する必要がありました。
KCバルツ2009

14

次のコマンドでは、検索でsvn2番目のを使用してフォルダーをフィルターで除外する必要がありませんgrep

grep -rL "foo" ./* | grep -v "\.svn"


6

私は幸運でした

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

での私の試みは、grep -v「foo」なしのすべての行を私に与えました。


4

問題

.phtmlインラインPHPコードを使用してHTMLを書き出すためにファイルを使用する大規模なプロジェクトをリファクタリングする必要があります。代わりにMustacheテンプレートを使用したいと思います。.phtml文字列new Mustacheを含まないガイルを見つけたいのですが、これらはまだ書き換える必要があります。

解決

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

説明

パイプの前:

探す

find . このディレクトリから、ファイルを再帰的に検索します

-iname '*.phtml'ファイル名には.phtmli大文字と小文字を区別しん)

-exec 'grep -H -E -o -c 'new Mustache' {}'grep一致した各パスでコマンドを実行します

グレップ

-H 常にファイル名ヘッダーと出力行を印刷します。

-E パターンを拡張正規表現として解釈します(つまり、grepをegrepとして動作させる)。

-o 行の一致する部分のみを印刷します。

-c 選択された行の数だけが標準出力に書き込まれます。


これにより.phtml、末尾がであるすべてのファイルパスのリストとnew Mustache、それぞれに文字列が出現する回数がカウントされます。

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

最初のパイプは、grep :0$このリストをフィルタリングして、で終わる行のみを含めます:0

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

2番目のパイプsed 's/..$//'は、各行の最後の2文字を取り除き、ファイルパスのみを残します。

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

3

gitを使用している場合は、すべての追跡ファイルが検索されます。

git grep -L "foo"

また、**サブディレクトリのグロビングがオンになっている場合は、追跡されたファイルのサブセットを検索できます(shopt -s globstar.bashrcで、これを参照してください):

git grep -L "foo" -- **/*.cpp

1

私のgrepには-Lオプションがありません。私はこれを達成するための回避策を見つけます。

アイデアは次のとおりです。

  1. 必要な文字列を含むすべてのファイル名をtxt1.txtにダンプします。
  2. ディレクトリ内のすべてのファイル名をtxt2.txtにダンプします。
  3. diffコマンドで2つのダンプファイルを区別します。

    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep ">"
    

私はコマンドを忘れていますが、ファイル名をダンプする代わりにdiff、システムがサポートしている場合は、2つの出力ストリームの間で実際に行うことができます(コマンドをかっこで囲み、そこに山かっこもあると思います)。それはサポートしていないので、問題ですgrep -L
Dexygen

1

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

「検索」でフィルターを指定し、「grep -vwE」で除外文字列を指定できます。変更された時間でもフィルタリングする必要がある場合は、findでmtimeを使用します。


これは文字列のないすべての行を表示しているようで、OPはファイル名のみを要求します。
ベンファーマー

1

バグレポートを開く

@tukanがコメントしたように、-L/ に関するAgの未解決のバグレポートがあります。--files-without-matchesフラグ。

バグレポートの進捗状況はほとんどないため、-L以下のオプションは当てにしないでください。が解決されていない限り、。代わりに、このスレッドで提示されているさまざまなアプローチを使用してください。バグレポートへのコメントの引用[強調は私のもの]:

これに関する更新はありますか?-Lファイルの最初の行の一致を完全に無視します。これはすぐに修正されないようですが、実際には宣伝されているように機能しないため、フラグは完全に削除する必要があります


シルバーサーチャー-Ag(目的の機能-バグレポートを参照)

の強力な代替手段として、シルバーサーチャー-Agをgrep使用できます。

速度に重点を置いた、ackに似たコード検索ツール。

を見るとman ag-Lまたは--files-without-matchesオプションが見つかります。

...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don´t contain matches.

つまり、現在のディレクトリから、一致しないファイルを再帰的に検索するには、次のようにしますfoo

ag -L foo

現在のディレクトリで一致しないファイルのみを検索fooするに--depth=0は、再帰を指定します。

ag -L foo --depth 0


@tukanプロンプトに感謝します。答えを更新しました。回答を削除するのではなく、バグに関する情報で開くことを選択します。
dfri 2018

1

grepに-Lオプションがない場合の代替手段(IBM AIXなど)で、grepとシェル以外はありません。

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

または

grep -ve "pattern" < file

上記のコマンドは、-vが検索されているパターンの逆を見つけるので、結果を提供します


1
これにより、パターンを含まない行が印刷されます。-lファイル名だけを印刷するオプションを追加できます。しかし、これはパターンを含まない行を含むファイルの名前を出力します。OPは、パターンを含む行を含まないファイルを検索したいと考えています。
tripleee 2016年

指定したコマンドは、「パターン」を含まないすべての行を含む「ファイルパス」内のファイルを一覧表示します。
アプロダン

-6

次のコマンドは、部分文字列「foo」を含む行をフィルタリングするのに役立ちます。

cat file | grep -v "foo"

2
これは、どの行にも一致が含まれていないファイルの名前ではなく、一致しない行を出力します。傷害に侮辱を加えるために、それはの役に立たない使用としてcat
tripleee 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.