私はよく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データベースが含まれます。
検索については、 ack をご覧になることをお勧めしますか?これはソースコードを認識するfind
であり、上記のようなソースコードリポジトリ情報を含む多くのファイルタイプを自動的に無視します。
なぜだけじゃないの
find . -not -iwholename '*.svn*'
-not述語は、パスのどこかに.svnがあるすべてを否定します。
だからあなたの場合は
find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;
次のように:
find . -path '*/.svn*' -Prune -o -print
または、代わりにパスプレフィックスではなくディレクトリに基づきます。
find . -name .svn -a -type d -Prune -o -print
.svn
、.git
、およびその他の隠しディレクトリ(ドットで始まる)を無視するには、次を試してください。
find . -type f -not -path '*/\.*'
ただし、find
を使用する目的がファイル内の検索である場合は、次のコマンドを使用してみてください。
git grep
-Gitリポジトリ内のパターンを検索するために特別に設計されたコマンド。ripgrep
-デフォルトでは、隠しファイルと.gitignore
で指定されたファイルを無視します。あなたの場合に私がすることは次のとおりです。
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
パターンを置き換えることができます。
GNU find
find . ! -regex ".*[/]\.svn[/]?.*"
この目的で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は呼び出し時にこれらのオプションを自動的に使用します
find . | grep -v \.svn
~/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;
簡単に理解できるgrepでコマンドをパイプしないのはなぜですか。
your find command| grep -v '\.svn'
私は簡単な代替をカレブと他の人の投稿(find -Prune
オプション、ack
、repofind
コマンドなどの使用を詳述したものに追加すると思いました。 )特に質問で説明した使用法に適用(および他の同様の使用法):
パフォーマンスのために、常にfind ... -exec grep ... +
(これを指摘してくれたKenjiに感謝)またはfind ... | xargs egrep ...
(ポータブル)またはfind ... -print0 | xargs -0 egrep ...
(GNU;スペースを含むファイル名で動作します)insteadfind ... -exec grep ... \;
の。
find ... -exec ... +
およびfind | xargs
フォームは、各ファイルごとにegrep
をフォークするのではなく、一度に多数のファイルをフォークするため、はるかに高速な実行になります。
find | xargs
フォームを使用する場合、grep
を使用して.svn
(または任意のディレクトリまたは正規表現)を簡単かつ迅速にプルーニングすることもできます。つまり、find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...
find
の-Prune
ロジックの設定方法を覚えておく必要はありません。)
find | grep | xargs
アプローチはGNU find
の-regex
オプション(ghostdog74
の投稿を参照)に似ていますが、より移植性があります(GNU find
は使用できません。)
ソースコードリポジトリでは、通常、テキストファイルに対してのみ処理を行います。
最初の行は、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
Findを-not -pathオプションとともに使用します。私はプルーンと幸運を持っていませんでした。
find . -name "*.groovy" -not -path "./target/*" -print
ターゲットディレクトリパスにないgroovyファイルを見つけます。
あなたがそうすることに注意してください
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
この問題を解決するには、次の検索条件を使用します。
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
wcfind
は、.svnディレクトリを自動的に削除するために使用するラッパー検索スクリプトです。
findrepo を試してください。これは、find/grepの単純なラッパーであり、ackよりはるかに高速です。この場合、次のように使用します。
findrepo uint 'messages.*'
私は通常、.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'
これは、Unixプロンプトで動作します
gfind。 \(-not -wholename '* \。svn *' \)-type f -name 'messages。*' -exec grep -Iw uint {} +
上記のコマンドは、.svnにないファイルをリストし、あなたが言及したgrepを実行します。