Joh*_*ica 221 linux svn bash grep find
我经常使用该find命令搜索源代码,删除文件等等.令人讨厌的是,因为Subversion在其.svn/text-base/目录中存储了每个文件的重复项,所以我的简单搜索最终会得到大量重复的结果.例如,我想以递归方式搜索uint多个messages.h和messages.cpp文件:
# 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;
Run Code Online (Sandbox Code Playgroud)
如何判断find忽略.svn目录?
更新:如果您将SVN客户端升级到1.7版,则不再是问题.
Subversion 1.7中引入的更改的一个关键特性是将工作副本元数据存储集中到一个位置.
.svnSubversion 1.7工作副本只有一个.svn目录 - 在工作副本的根目录中,而不是工作副本中每个目录中的目录.该目录包括(除其他外)一个SQLite支持的数据库,该数据库包含该工作副本所需的所有元数据Subversion.
wha*_*ley 290
为什么不呢
find . -not -iwholename '*.svn*'
Run Code Online (Sandbox Code Playgroud)
-not谓词否定了路径中任何地方的.svn.
所以在你的情况下它会
find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;
Run Code Online (Sandbox Code Playgroud)
        Kal*_*son 140
如下:
find . -path '*/.svn*' -prune -o -print
Run Code Online (Sandbox Code Playgroud)
或者,或者基于目录而不是路径前缀:
find . -name .svn -a -type d -prune -o -print
Run Code Online (Sandbox Code Playgroud)
        Bri*_*new 65
为了搜索,我可以建议你看看ack吗?它是源代码识别的find,因此会自动忽略许多文件类型,包括上面的源代码存储库信息.
ken*_*orb 31
要忽略.svn,.git以及其他隐藏目录(以点开头),请尝试:
find . -type f -not -path '*/\.*'
Run Code Online (Sandbox Code Playgroud)
但是,如果使用的目的find是在文件中搜索,您可以尝试使用这些命令:
git grep - 专门设计的命令,用于在Git存储库中搜索模式.ripgrep- 默认情况下忽略在中指定的隐藏文件和文件.gitignore.Ant*_*ine 18
这是我在你的情况下会做的:
find . -path .svn -prune -o -name messages.* -exec grep -Iw uint {} +
Run Code Online (Sandbox Code Playgroud)
Emacs的rgrep内置命令会忽略.svn目录,以及执行a时可能不感兴趣的更多文件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
Run Code Online (Sandbox Code Playgroud)
它忽略了大多数版本控制系统创建的目录,以及许多编程语言的生成文件.您可以创建一个别名来调用此命令,并替换find和grep模式以解决您的特定问题.
Ron*_*del 10
我为此目的使用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"
Run Code Online (Sandbox Code Playgroud)
grep在调用时自动使用这些选项
创建一个名为的脚本~/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
Run Code Online (Sandbox Code Playgroud)
此脚本的行为与普通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;
Run Code Online (Sandbox Code Playgroud)
        小智 8
find . | grep -v \.svn 
为什么不用grep管理你的命令,这很容易理解:
your find command| grep -v '\.svn'
Run Code Online (Sandbox Code Playgroud)
        只是想我会添加一个简单的替代 Kaleb和其他人的帖子(详细使用find -prune选项ack,repofind命令等),这特别适用于你在问题中描述的用法(和任何其他类似的用法):
出于性能考虑,你应该总是尝试使用find ... -exec grep ... +(感谢贤治指出了这一点)或find ... | xargs egrep ...(便携式)或find ... -print0 | xargs -0 egrep ...(GNU;适用于含有空格的文件名)来代替的find ... -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不可用的平台.)
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           83675 次  |  
        
|   最近记录:  |