IT story

.svn 디렉토리를 무시하기 위해`find`를 어떻게 얻을 수 있습니까?

hot-time 2020. 4. 23. 08:01
반응형

.svn 디렉토리를 무시하기 위해`find`를 어떻게 얻을 수 있습니까?


나는 종종 find명령을 사용하여 소스 코드를 검색하고 파일을 삭제합니다. 귀찮게도 Subversion은 .svn/text-base/디렉토리 에 각 파일의 복제본을 저장하기 때문에 간단한 검색으로 인해 많은 중복 결과가 발생합니다. 예를 들어, 나는 재귀 적으로 검색 할 uint여러에서 messages.hmessages.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;

디렉토리 find를 무시하도록 어떻게 알 수 .svn있습니까?


업데이트 : SVN 클라이언트를 버전 1.7로 업그레이드하면 더 이상 문제가되지 않습니다.

Subversion 1.7에서 도입 된 변경 사항의 주요 기능은 작업 사본 메타 데이터 스토리지를 단일 위치로 중앙 집중화하는 것입니다. .svn작업 복사본의 모든 디렉터리에 있는 디렉터리 대신 Subversion 1.7 작업 복사본에는 작업 복사본 .svn의 루트에 하나의 디렉터리 있습니다. 이 디렉토리에는 무엇보다도 해당 작업 복사본에 필요한 모든 메타 데이터 메타 데이터를 포함하는 SQLite 지원 데이터베이스가 포함됩니다.


검색을 위해 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.

관련 : Linux에서 특정 텍스트를 포함하는 모든 파일을 찾으려면 어떻게합니까?


내가 당신의 경우에 할 것입니다 :

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 .  ! -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은 자동으로 호출시이 옵션을 사용합니다


다음과 같은 스크립트를 작성하십시오 ~/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;

find . | grep -v \.svn


쉽게 이해할 수있는 grep으로 명령을 파이프하지 않는 이유는 무엇입니까?

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

그냥 내가 추가 거라고 생각 간단한 대안 (의 사용을 설명하는 Kaleb의 및 다른 사람의 게시물 find -prune, 옵션 ack, repofind명령 등) 인 당신이 질문에 기술 한 사용에 특히 적용 (및 기타 이와 유사한 용도) :

  1. 성능을 위해, 당신은 항상 사용하려고해야 find ... -exec grep ... +하거나 (이 지적에 대한 감사 켄지) find ... | xargs egrep ...(휴대용) 또는 find ... -print0 | xargs -0 egrep ...(공백이 포함 된 파일 이름에 작품 GNU)을 대신find ... -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를 사용할 수없는 플랫폼에서도 작동 함 ).


소스 코드 저장소에서는 일반적으로 텍스트 파일에 대해서만 작업을 수행하려고합니다.

첫 번째 줄은 CVS, SVN 및 GIT 리포지토리 파일을 제외한 모든 파일입니다.

두 번째 줄은 모든 이진 파일을 제외합니다.

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

-not -path 옵션과 함께 find를 사용합니다. 나는 자두로 운이 없었습니다.

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

대상 디렉토리 경로에 groovy 파일이 없습니다.


find / grep 주위의 간단한 래퍼이고 ack보다 훨씬 빠른 findrepo사용해보십시오 .

findrepo uint 'messages.*'

wcfind .svn 디렉토리를 자동으로 제거하는 데 사용하는 찾기 래퍼 스크립트입니다.


이 문제를 해결하려면 다음 찾기 조건을 사용하면됩니다.

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


당신이 할 경우

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

다음 -print전체 식 (때 암시하지 않습니다 -type f -name 'messages.*') 사실 (같은 '행동'이 더 있기 때문에, -exec).

특정 디렉토리로의 내림차순을 중지하려면 해당 디렉토리와 일치하는 것을 사용하고 그 뒤를 따라야합니다 -prune(디렉토리 내림차순 중지). 이렇게 :

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

이것은 .svn 디렉토리에 대해 True평가되며 , -o(OR) 로 다음을 수행하여 부울 단락을 사용할 수 있습니다 . 이후 -o첫 번째 부분이 False 일 때에 만 다음에 나오는 것이 확인되므로 .svn 디렉토리 아닙니다 . 다시 말해 다음과 같습니다.

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

단지 오른쪽의 무엇 evalute 것 -o, 즉, -name 'message.*' -exec grep -Iw uint {}NOT 내부 파일을 .svn 디렉토리에 대해.

그 때문에주의 .svn'. 메시지 *'가능성이 항상 디렉토리 (그리고 예를 들어 파일),이 경우에 확실히 이름과 일치하지 않습니다, 당신은뿐만 아니라을 떠날 수 -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


이것은 유닉스 프롬프트에서 나를 위해 작동합니다.

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

위의 명령은 .svn이 아닌 파일을 나열하고 언급 한 grep을 수행합니다.


나는 보통 grep을 통해 출력을 한 번 더 .svn을 제거하여 파이프로 사용합니다. 사용시 속도가 훨씬 느리지 않습니다. 전형적인 예 :

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

또는

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

참고 URL : https://stackoverflow.com/questions/2314643/how-can-i-get-find-to-ignore-svn-directories

반응형