私のお気に入りのBASHコマンドのひとつは、
find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;
指定されたSearchStringについて、現在のディレクトリ以下のすべてのファイルの内容を検索します。開発者として、これは時々便利になりました。
私の現在のプロジェクトと私のコードベースの構造のために、しかし、私は "。svn"を含むディレクトリの中または下にあるファイル、またはそれを含むファイルを検索しないことによってこのBASHコマンドをさらにもっともっとしたい".html"で終わる
見つけるためのMANページは私を混乱させます。私は-Pruneを使ってみましたが、奇妙な振る舞いをしました。 (開始するために).htmlページだけをスキップしようとして、私は試してみました。
find . -wholename './*.html' -Prune -exec grep 'SearchString' {} /dev/null \;
そして私が望んでいた行動を得られませんでした。私は-Pruneのポイントを見逃しているかもしれないと思います。あなたは私を助けてもらえますか?
ありがとう
Findの否定(!)機能を使用して、特定の名前のファイルと一致させないことができます。
find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;
そのため、名前の末尾が.htmlであるか、パス内の任意の場所に.svnが含まれていると、一致しないため、execは実行されません。
私は長い間同じ問題を抱えていました、そして異なる状況に適用できるいくつかの解決策があります:
ack-grep
は一種の "開発者のgrep
"であり、はデフォルトではバージョン管理ディレクトリと一時ファイルをスキップします。 man
ページでは特定のファイルタイプのみを検索する方法と 自分で定義する方法 を説明しています。grep
自身の--exclude
と--exclude-dir
オプションはファイルglobsとsingleディレクトリをスキップするためにとても簡単に使うことができます。ディレクトリ、残念ながら)。find . \( -type d -name '.svn' -o -type f -name '*.html' \) -Prune -o -print0 | xargs -0 grep ...
は動作するはずですが、上記のオプションはおそらく長期的には面倒ではありません。次のfind
コマンドは、名前に.svn
が含まれているディレクトリをPruneします。ディレクトリには降りませんが、整理されたパス名が出力されます(-name '*.svn'
が原因です)。 。
:grep -d skip
でディレクトリ名を除外することができます。これはそのような入力「ディレクトリ名」を黙ってスキップします。
GNU grepでは、-H
の代わりに/dev/null
を使用できます。ちょっとした副次的な問題として、\+
は\;
よりはるかに速い可能性があります。 100万行のファイルでは、\;
を使用すると4m20s、\+
を使用すると1.2sしかかかりませんでした。
次の方法では、-exec
の代わりにxargs
を使用し、どのファイルの名前にも改行\n
がないと仮定します。ここで使用されているように、xargs
はfindの\+
とほとんど同じです。
xargs
は、'\n'
オプションを使用して入力区切り文字を-d
に変更することによって、連続したスペースを含むファイル名を渡すことができます。
これは、名前が.svn
を含み、.html
で終わらないファイルのみをgrepsするディレクトリを除外します。
find . \( -name '*.svn*' -Prune -o ! -name '*.html' \) |
xargs -d '\n' grep -Hd skip 'SearchString'