web-dev-qa-db-ja.com

.findを取得して.svnディレクトリを無視するにはどうすればよいですか?

私はよくfindコマンドを使用して、ソースコードの検索、ファイルの削除などを行います。迷惑なことに、Subversionは.svn/text-base/ディレクトリに各ファイルの重複を保存するため、単純な検索では多くの重複した結果が得られます。たとえば、複数のmessages.hおよびmessages.cppファイルでuintを再帰的に検索したい場合:

# find -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp:            Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp:    Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp:                Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp:        Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp:        for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./.svn/text-base/messages.cpp.svn-base:    Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:                Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:        Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:        for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h:    void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h:    ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h:    uint        _scanCount;
./virus/.svn/text-base/messages.cpp.svn-base:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.cpp.svn-base:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.h.svn-base:    void _progress(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base:    ProgressMessage(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base:    uint        _scanCount;

find.svnディレクトリを無視するように指示するにはどうすればよいですか?


Update:SVNクライアントを version 1.7 にアップグレードする場合、これはもはや問題ではありません。

Subversion 1.7で導入された変更の主要な機能は、作業コピーのメタデータストレージを1つの場所に集中化することです。作業コピーのすべてのディレクトリにある.svnディレクトリの代わりに、Subversion 1.7作業コピーには、作業コピーのルートに.svnディレクトリが1つだけあります。このディレクトリには、(特に)その作業コピーにSubversionが必要とするすべてのメタデータを含むSQLite-backedデータベースが含まれます。

219
John Kugelman

検索については、 ack をご覧になることをお勧めしますか?これはソースコードを認識するfindであり、上記のようなソースコードリポジトリ情報を含む多くのファイルタイプを自動的に無視します。

64
Brian Agnew

なぜだけじゃないの

find . -not -iwholename '*.svn*'

-not述語は、パスのどこかに.svnがあるすべてを否定します。

だからあなたの場合は

find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;
287
whaley

次のように:

find . -path '*/.svn*' -Prune -o -print

または、代わりにパスプレフィックスではなくディレクトリに基づきます。

find . -name .svn -a -type d -Prune -o -print
140
Kaleb Pederson

.svn.git、およびその他の隠しディレクトリ(ドットで始まる)を無視するには、次を試してください。

find . -type f -not -path '*/\.*'

ただし、findを使用する目的がファイル内の検索である場合は、次のコマンドを使用してみてください。

  • git grep-Gitリポジトリ内のパターンを検索するために特別に設計されたコマンド。
  • ripgrep -デフォルトでは、隠しファイルと.gitignoreで指定されたファイルを無視します。

関連: Linuxで特定のテキストを含むすべてのファイルを見つける方法

31
kenorb

あなたの場合に私がすることは次のとおりです。

find . -path .svn -Prune -o -name messages.* -exec grep -Iw uint {} +

Emacsのrgrep組み込みコマンドは、.svnディレクトリを無視します。また、find | grepを実行するときに、おそらく興味のない多くのファイルを無視します。デフォルトで使用するものは次のとおりです。

find . \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS \
          -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr \
          -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{Arch\} \) \
     -Prune -o \
       \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin \
          -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg \
          -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo \
          -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm \
          -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem \
          -o -name \*.x86f -o -name \*.sparcf -o -name \*.fasl -o -name \*.ufsl \
          -o -name \*.fsl -o -name \*.dxl -o -name \*.pfsl -o -name \*.dfsl \
          -o -name \*.p64fsl -o -name \*.d64fsl -o -name \*.dx64fsl -o -name \*.lo \
          -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc \
          -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky \
          -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps \
          -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps \
          -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) \
     -Prune -o \
     -type f \( -name pattern \) -print0 \
     | xargs -0 -e grep -i -nH -e regex

ほとんどのバージョン管理システムで作成されたディレクトリや、多くのプログラミング言語用に生成されたファイルは無視されます。このコマンドを呼び出すエイリアスを作成し、特定の問題のfindおよびgrepパターンを置き換えることができます。

18
Antoine

GNU find

find .  ! -regex ".*[/]\.svn[/]?.*"
12
ghostdog74

この目的でgrepを使用します。これを〜/ .bashrcに入れてください

export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn"

grepは呼び出し時にこれらのオプションを自動的に使用します

10
Ronny Brendel

find . | grep -v \.svn

8
me.

~/bin/svnfindというスクリプトを作成します。

#!/bin/bash
#
# Attempts to behave identically to a plain `find' command while ignoring .svn/
# directories.

OPTIONS=()
PATHS=()
EXPR=()

while [[ $1 =~ ^-[HLP]+ ]]; do
    OPTIONS+=("$1")
    shift
done

while [[ $# -gt 0 ]] && ! [[ $1 =~ '^[-(),!]' ]]; do
    PATHS+=("$1")
    shift
done

# If user's expression contains no action then we'll add the normally-implied
# `-print'.
ACTION=-print

while [[ $# -gt 0 ]]; do
    case "$1" in
       -delete|-exec|-execdir|-fls|-fprint|-fprint0|-fprintf|-ok|-print|-okdir|-print0|-printf|-Prune|-quit|-ls)
            ACTION=;;
    esac

    EXPR+=("$1")
    shift
done

if [[ ${#EXPR} -eq 0 ]]; then
    EXPR=(-true)
fi

exec -a "$(basename "$0")" find "${OPTIONS[@]}" "${PATHS[@]}" -name .svn -type d -Prune -o '(' "${EXPR[@]}" ')' $ACTION

このスクリプトは、プレーンfindコマンドと同じように動作しますが、.svnディレクトリを削除します。それ以外の場合、動作は同じです。

例:

# svnfind -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp:            Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp:    Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp:                Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp:        Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp:        for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h:    void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h:    ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h:    uint        _scanCount;
8
John Kugelman

簡単に理解できるgrepでコマンドをパイプしないのはなぜですか。

your find command| grep -v '\.svn'
7
Vijay

私は簡単な代替をカレブと他の人の投稿(find -Pruneオプション、ackrepofindコマンドなどの使用を詳述したものに追加すると思いました。 )特に質問で説明した使用法に適用(および他の同様の使用法):

  1. パフォーマンスのために、常にfind ... -exec grep ... +(これを指摘してくれたKenjiに感謝)またはfind ... | xargs egrep ...(ポータブル)またはfind ... -print0 | xargs -0 egrep ...(GNU;スペースを含むファイル名で動作します)insteadfind ... -exec grep ... \;の。

    find ... -exec ... +およびfind | xargsフォームは、各ファイルごとにegrepをフォークするのではなく、一度に多数のファイルをフォークするため、はるかに高速な実行になります。

  2. find | xargsフォームを使用する場合、grepを使用して.svn(または任意のディレクトリまたは正規表現)を簡単かつ迅速にプルーニングすることもできます。つまり、find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...find-Pruneロジックの設定方法を覚えておく必要はありません。)

    find | grep | xargsアプローチはGNU find-regexオプション(ghostdog74の投稿を参照)に似ていますが、より移植性があります(GNU findは使用できません。)

5
vladr

ソースコードリポジトリでは、通常、テキストファイルに対してのみ処理を行います。

最初の行は、CVS、SVN、およびGITリポジトリファイルを除くすべてのファイルです。

2行目は、すべてのバイナリファイルを除外します。

find . -not \( -name .svn -Prune -o -name .git -Prune -o -name CVS -Prune \) -type f -print0 | \
xargs -0 file -n | grep -v binary | cut -d ":" -f1
4
rickfoosusa

Findを-not -pathオプションとともに使用します。私はプルーンと幸運を持っていませんでした。

find .  -name "*.groovy" -not -path "./target/*" -print

ターゲットディレクトリパスにないgroovyファイルを見つけます。

3
scott m gardner

あなたがそうすることに注意してください

find . -type f -name 'messages.*'

式(-print)が真の場合は、-type f -name 'messages.*'が暗示されます。これは、「アクション」がないためです(-execなど)。

一方、特定のディレクトリへの下降を停止するには、それらのディレクトリに一致するものを使用し、その後に-Prune(ディレクトリへの下降を停止することを目的とする)を使用する必要があります。そのようです:

find . -type d -name '.svn' -Prune

これは.svnディレクトリに対してTrueに評価され、これに-o(OR)を続けることでブール短絡を使用できます。その後、-oの後に続くものは最初の部分がFalseの場合にのみチェックされます、したがってnotは.svnディレクトリです。言い換えれば、次のとおりです。

find . -type d -name '.svn' -Prune -o -name 'message.*' -exec grep -Iw uint {}

.svnディレクトリ内にないファイルについては、-oの右側、つまり-name 'message.*' -exec grep -Iw uint {}のみを評価します。

.svnは常にディレクトリ(たとえばファイルではない)である可能性があり、この場合は確かに名前 'message。*'と一致しないため、-type dを省いて次のようにすることもできます。

find . -name '.svn' -Prune -o -name 'message.*' -exec grep -Iw uint {}

最後に、アクションを省略した場合(-execはアクションです)、次のように言うことに注意してください。

find . -name '.svn' -Prune -o -name 'message.*'

その後、-printアクションが暗示されますが、-name '.svn' -Prune -o部分を含むWHOLE式に適用されるため、すべての.svnディレクトリと 'message。*'ファイルが出力されます。したがって、このように-Pruneを使用する場合は、ブール式の右側で「アクション」を常に使用する必要があります。そして、そのアクションが印刷されているときは、次のように明示的に追加する必要があります。

find . -name '.svn' -Prune -o -name 'message.*' -print

2
Carlo Wood

この問題を解決するには、次の検索条件を使用します。

find \( -name 'messages.*' ! -path "*/.svn/*" \) -exec grep -Iw uint {} +

次のような制限を追加できます。

find \( -name 'messages.*' ! -path "*/.svn/*" ! -path "*/CVS/*" \) -exec grep -Iw uint {} +

詳細については、マニュアルページのセクション「演算子」を参照してください。 http://unixhelp.ed.ac.uk/CGI/man-cgi?find

2
Code-Source

wcfind は、.svnディレクトリを自動的に削除するために使用するラッパー検索スクリプトです。

2
leedm777

findrepo を試してください。これは、find/grepの単純なラッパーであり、ackよりはるかに高速です。この場合、次のように使用します。

findrepo uint 'messages.*'
2
pixelbeat

私は通常、.svnを削除して、もう一度grepを介して出力をパイプ処理します。私の使用では、それほど遅くはありません。典型的な例:

find -name 'messages.*' -exec grep -Iw uint {} + | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'

OR

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'
1
geminiimatt

これは、Unixプロンプトで動作します

gfind。 \(-not -wholename '* \。svn *' \)-type f -name 'messages。*' -exec grep -Iw uint {} +

上記のコマンドは、.svnにないファイルをリストし、あなたが言及したgrepを実行します。

1
Felix