Jak mogę zmusić `find` do zignorowania katalogów .svn?

227

Często używam findpolecenia do przeszukiwania kodu źródłowego, usuwania plików, cokolwiek. Irytujące, ponieważ Subversion przechowuje duplikaty każdego pliku w swoich .svn/text-base/katalogach, moje proste wyszukiwania kończą się uzyskaniem wielu duplikatów wyników. Na przykład, chcę rekursywnie szukać uintw wielokrotności messages.hi messages.cppplików:

# 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;

Jak mogę findzignorować .svnkatalogi?


Aktualizacja : jeśli uaktualnisz swojego klienta SVN do wersji 1.7, nie będzie to już problemem.

Kluczową cechą zmian wprowadzonych w Subversion 1.7 jest centralizacja przechowywania metadanych kopii roboczej w jednym miejscu. Zamiast .svnkatalogu w każdym katalogu w kopii roboczej, kopie robocze Subversion 1.7 mają tylko jeden .svnkatalog - w katalogu głównym kopii roboczej. Ten katalog zawiera (między innymi) bazę danych opartą na SQLite, która zawiera wszystkie potrzebne metadane Subversion dla tej kopii roboczej.

John Kugelman
źródło
4
Aby uzyskać wydajność, spróbuj użyć find ... -print0 | xargs -0 egrep ...zamiast find ... -exec grep ...(nie rozwidla się grepdla każdego pliku, ale dla kilku plików jednocześnie). Za pomocą tego formularza można również przycinać .svnkatalogi bez korzystania z -pruneopcji find, tj.find ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
vladr
3
@Vlad: O ile wiem, używanie -execz +nie rozwidla grepdla każdego pliku, podczas gdy używanie z ;robi. Używanie -execjest właściwie bardziej poprawne niż używanie xargs. Zauważ, że polecenia takie jak lscoś robią, nawet jeśli lista argumentów jest pusta, podczas gdy polecenia takie chmoddają błąd, jeśli nie ma wystarczających argumentów. Aby zobaczyć, co mam na myśli, po prostu spróbuj następującą komendę w katalogu, który nie ma żadnego skrypt: find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755. Porównaj z tego: find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'.
Siu Ching Pong -Asuka Kenji-
2
@Vlad: Poza tym greprezygnacja .svnnie jest dobrym pomysłem. Chociaż findjest wyspecjalizowany w obsłudze właściwości plików, grepnie robi tego. W twoim przykładzie plik o nazwie „.svn.txt” również zostanie odfiltrowany przez twoje egreppolecenie. Chociaż możesz zmodyfikować wyrażenie regularne na „^ / \. Svn $” , nadal nie jest to dobrą praktyką. -pruneOrzecznik finddziała idealnie do filtrowania plików (według nazwy pliku lub tworzenia datownik, czy cokolwiek warunek ty zestawie). To tak, jakby nawet jeśli możesz zabić karalucha za pomocą dużego miecza, nie oznacza to, że jest to sugerowany sposób :-).
Siu Ching Pong -Asuka Kenji-
3
Przejście na Git rozwiązało ten problem (między innymi). W tworzy folder .git tylko w katalogu głównym kopii roboczej, a nie w każdym jego folderze, takim jak SVN. Ponadto folder .git nie zawiera zwykłych plików, które byłyby mylone z rzeczywistymi plikami o tych samych nazwach.
Tronic,
3
2Dan Molding: svn 1.7 tworzy tylko jeden katalog .svn najwyższego poziomu
ccpizza

Odpowiedzi:

65

Do wyszukiwania, czy mogę zasugerować spojrzenie na ack ? Jest świadomy kodu źródłowego findi jako taki automatycznie ignoruje wiele typów plików, w tym informacje o repozytorium kodu źródłowego, takie jak powyższe.

Brian Agnew
źródło
3
Bardzo mi się podoba ack, ale uważam, że jest znacznie wolniejszy niż w find -type f -name "*.[ch]" | xargs grepprzypadku dużej bazy kodu.
John Ledbetter
63
John, jestem autorem ack i jeśli możesz podać mi szczegóły problemów z szybkością ack vs. grep, byłbym wdzięczny. Były całkowicie porównywalne we wszystkich przypadkach, które znalazłem. Daj mi znać na github.com/petdance/ack/issues lub napisz do mnie na andy na petdance.com. Thansk.
Andy Lester
63
Chłopaki, to wskazówka, ale zdecydowanie nie odpowiedź na pytanie! :)
dolzenko,
8
Czy ackrozliczenie nie jest lepsze grep, nie świadome źródła find? Niektóre przykłady użycia go do zastąpienia findsprawiłyby, że jest to prawdziwa odpowiedź.
michiakig,
3
To odpowiedź na pytanie, o które nie wiedział, że zadaje. =)
Frungi
293

dlaczego nie tylko

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

Predykat -not neguje wszystko, co ma .svn w dowolnym miejscu na ścieżce.

W twoim przypadku tak by było

find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;
wieloryb
źródło
5
Super duża +1 dla „-not” i „-iwholename”. Ack jest cudowny i używam go, ale find / exec wciąż ma swoje zastosowania.
David Blevins,
9
Jedyna odpowiedź, która faktycznie odpowiedziała na pierwotne pytanie.
Brendon Crawford,
14
Jestem zdecydowanie poza swoim żywiołem i jestem pewien, że będę krytykowany za ten komentarz, ale najwyraźniej -nie i -nazwa-nazwy nie są zgodne z POSIX. Użyłem ! zamiast -not i -path zamiast -iwholename i uzyskał te same wyniki. Według moich stron podręcznika (Ubuntu 12.04) ta składnia jest zgodna z POSIX.
Jan
1
@ whaley Na początku powiedziałeś, '*.svn*'ale potem '*.svn'. Który jest poprawny? Czy oba działają? Myślę, że tak powinno być '*.svn*'?
Keith M
1
@KeithM great catch faktycznie. Ta odpowiedź jest obecna od lat i nie sądzę, żeby ktokolwiek ją złapał do tej pory.
whaley
141

Następująco:

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

Lub alternatywnie na podstawie katalogu, a nie prefiksu ścieżki:

find . -name .svn -a -type d -prune -o -print
Kaleb Pederson
źródło
14
@Kaleb: Cześć. Sugeruję, find . -type d -name .svn -prune -o -printponieważ jest trochę szybszy. Zgodnie ze standardem POSIX wyrażenia są przetwarzane jeden po drugim, w określonej kolejności. Jeśli pierwszym wyrażeniem -ajest false, drugie wyrażenie nie będzie oceniane (zwane również zwarciem i oceną ).
Siu Ching Pong -Asuka Kenji-
2
@Kaleb: Ponieważ porównywanie typu pliku (równoważne testowaniu, czy bit jest ustawiony na liczbę całkowitą) jest szybsze niż porównywanie nazwy pliku (równoważne porównywaniu ciągów, którym jest O (n)), wstawianie -type dprzed -name .svnjest teoretycznie bardziej wydajne. Jest to jednak zwykle nieznaczne, z wyjątkiem bardzo dużego drzewa katalogów.
Siu Ching Pong -Asuka Kenji-
5
@ SiuChingPong-AsukaKenji- nie, porównywanie tylko nazwy pliku jest szybsze, ponieważ -type wymaga wywołania stat (2) dla każdego pliku. Nazwa pliku jest jednak częścią odpowiedzi readdir (3).
hraban
3
@JathanathanHartley Tęsknisz -printza częścią ostatniego wyrażenia. Coś jak find . -name .git -prune -o \( -type f -name LICENSE -print \)działa zgodnie z oczekiwaniami.
sschuberth
1
Jeśli chcesz ignorować zarówno .git i .svn i po prostu wymienić inne katalogi find . -name .svn -prune -o -name .git -prune -o -type d -print. Może to być kilka milisekund szybsze wstawianie -type dprzed tymi dwoma -name, ale nie jest warte dodatkowego pisania.
JPaget
34

Ignorować .svn, .giti innych ukrytych katalogów (zaczynające się od kropki), spróbuj:

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

Jeśli jednak celem findjest wyszukiwanie w plikach, możesz spróbować użyć tych poleceń:

  • git grep - specjalnie zaprojektowane polecenie do wyszukiwania wzorców w repozytorium Git.
  • ripgrep- który domyślnie ignoruje ukryte pliki i pliki określone w .gitignore.

Powiązane: Jak znaleźć wszystkie pliki zawierające określony tekst w systemie Linux?

kenorb
źródło
Najlepsza odpowiedź imo. Inni próbują wyjaśnić rzeczy, które nie odpowiadają na proste pytanie.
Anthony
19

Oto, co bym zrobił w twoim przypadku:

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

rgrepWbudowane polecenie Emacsa ignoruje .svnkatalog i wiele innych plików, którymi prawdopodobnie nie jesteś zainteresowany podczas wykonywania find | grep. Oto, czego używa domyślnie:

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

Ignoruje katalogi tworzone przez większość systemów kontroli wersji, a także generowane pliki dla wielu języków programowania. Możesz utworzyć alias, który wywołuje to polecenie oraz zastępuje findi grepwzorce dla określonych problemów.

Antoine
źródło
12

Znajdź GNU

find .  ! -regex ".*[/]\.svn[/]?.*"
ghostdog74
źródło
Ładowałem ścieżki katalogu do tablicy, aby PHP mógł je przetworzyć. Inne odpowiedzi wyżej (z jakiegokolwiek powodu) nie odfiltrowały plików w znalezieniu (pomimo -type d) - ta odpowiedź zrobiła. +1
be hollenbeck
11

W tym celu używam grep. Umieść to w swoim ~ / .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 automatycznie używa tych opcji przy wywołaniu

Ronny Brendel
źródło
1
Warto zauważyć, że „grep” zyskał opcję „--exclude-dir” rok lub dwa lata temu. Najnowsze dystrybucje Linuksa obejmują to, ale jeśli dobrze pamiętam, musiałem skompilować własny grep (lub poprosić homebrew o zrobienie tego) na OSX.
Jonathan Hartley,
Używam niewielkiego wariantu tego. Mój .bashrc tworzy funkcję Bash „grp”, która jest zdefiniowana jako GREP_OPTIONS=xxx grep "$@". Oznacza to, że zmienna GREP_OPTIONS jest ustawiona tylko dla instancji grep, które uruchamiam ręcznie za pomocą 'grp'. Oznacza to, że nigdy nie dostaję sytuacji, w której uruchamiam narzędzie i wewnętrznie wywołuje grep, ale narzędzie się myli, ponieważ grep nie zachowuje się tak, jak się spodziewał. Mam też drugą funkcję „grpy”, która nazywa się „grp”, ale dodaje --include=*.py, tylko do wyszukiwania plików w języku Python.
Jonathan Hartley,
Właściwie po zastanowieniu zrobienie tego po swojemu wcale nie musi już używać GREP_OPTIONS. Teraz mam tylko funkcję powłoki „grp”, która wywołuje grep --exclude=tags --exclude_dir=.git ...etc... "$@". Podoba mi się, że działa to jak „ack”, ale zachowuję świadomość i kontrolę nad tym, co robi.
Jonathan Hartley,
9

find . | grep -v \.svn

mnie.
źródło
Musisz uciec .w .svnwyrażeniu regularnym.
vladr
4
Użyj --fixed-string z grep: | fgrep -v /.svn/lub `| grep -F -v / .svn / `, aby wykluczyć dokładnie katalog, a nie pliki z„ .svn ”jako częścią ich nazwy.
Stephen P
8

Dlaczego nie podajesz polecenia grep, co jest łatwo zrozumiałe:

your find command| grep -v '\.svn'
Vijay
źródło
Musisz uciec .w .svnwyrażeniu regularnym.
vladr
@Yclian bez cienia wątpliwości; jeśli tego nie zrobisz, katalogi o nazwach „tsvn”, „1svn”, „asvn” itd. również będą ignorowane od „”. jest wyrażeniem regularnym wyrażenia regularnego: „dopasuj dowolny znak”.
vladr
W porządku, myślałem, że stanie się tak tylko w przypadku -E i -G. Właśnie przetestowałem, mój zły. :(
yclian
2
Podoba mi się ta odpowiedź, ponieważ jest ona koncepcyjnie prostsza niż wszystkie inne. Nie pamiętam absurdalnej składni użycia „znajdź”, ale zdecydowanie pamiętam, jak używać grep -v, ponieważ jest on używany w bardzo wielu sytuacjach.
mattismyname
8

Utwórz skrypt o nazwie ~/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

Ten skrypt zachowuje się identycznie jak zwykłe findpolecenie, ale usuwa .svnkatalogi. W przeciwnym razie zachowanie jest identyczne.

Przykład:

# 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;
John Kugelman
źródło
Ten skrypt nie działa zgodnie z oczekiwaniami. Uruchamiając go z opcją „svnfind -type f”, drukuje również katalogi svn i pliki w katalogach svn
Ingo Fischer
@ifischer Czy możesz dodać echopolecenie do polecenia find i powiedzieć, które polecenie jest wykonywane? svnfind -type fdziała świetnie na mojej maszynie Red Hat.
John Kugelman,
Ok, więc wydaje się, że zależy od systemu operacyjnego. Używam Debian Squeeze (to samo na Ubuntu). Nie rozumiem, co masz na myśli przez „dodaj echo”?
Ingo Fischer
@ ifischer Zmień ostatni wiersz na, echo find "${OPTIONS[@]}"...aby wypisał polecenie find zamiast go uruchomić.
John Kugelman,
Ok zmieniłem ostatni wiersz na echo find ${OPTIONS[@]} ${PATHS[@]} -name .svn -type d -prune -o ( ${EXPR[@]} ) $ACTION, To daje mi następujące dane wyjściowe:find -type f -name .svn -type d -prune -o ( -true ) -print
Ingo Fischer
5

Pomyślałem, że dodam prostą alternatywę do postów Kaleba i innych (która szczegółowo opisuje użycie find -pruneopcji ack, repofindpoleceń itp.), Która ma szczególne zastosowanie do użycia opisanego w pytaniu (i innych podobnych zastosowaniach):

  1. Pod kątem wydajności, należy zawsze próbować używać find ... -exec grep ... +(dzięki Kenji za wskazanie na to uwagę) lub find ... | xargs egrep ...(przenośny) lub find ... -print0 | xargs -0 egrep ...(GNU; prace o nazwach zawierających spacje) zamiast z find ... -exec grep ... \;.

    Formy find ... -exec ... +i find | xargsnie rozwidlają się egrepdla każdego pliku, ale dla kilku plików jednocześnie, co powoduje znacznie szybsze wykonanie .

  2. Podczas korzystania z find | xargsformularza można także użyć grepdo łatwo i szybko suszonych śliwek .svn(lub dowolne katalogi lub wyrażenie regularne), to znaczy find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...(przydatne, gdy trzeba coś szybko i nie może być jedno, aby pamiętać, jak skonfigurować find„s -prunelogiki).

    find | grep | xargsPodejście jest podobne do GNU find„s -regexopcji (patrz ghostdog74” s post), ale jest bardziej przenośny (będzie również działać na platformach GNU, gdzie findnie jest możliwe).

Vladr
źródło
1
@Vlad: Zwróć uwagę, że istnieją dwie formy -execprzejścia find: jedna kończy się na, ;a druga kończy się na +. Ten, który kończy się na, +zastępuje {}listą wszystkich pasujących plików. Poza tym wyrażenie regularne '/\.svn'pasuje do nazw plików takich jak '.svn.txt'. Więcej informacji można znaleźć w moich komentarzach do pytania.
Siu Ching Pong -Asuka Kenji-
2
@Vlad: Oto standard POSIX dla findnarzędzia. Proszę zobaczyć -execczęść :-).
Siu Ching Pong -Asuka Kenji-
4

W repozytorium kodu źródłowego na ogół chcę robić tylko pliki tekstowe.

Pierwszy wiersz to wszystkie pliki, z wyjątkiem plików repozytorium CVS, SVN i GIT.

Drugi wiersz wyklucza wszystkie pliki binarne.

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
rickfoosusa
źródło
3

Używam find z opcjami -not -path. Nie miałem szczęścia z suszonymi śliwkami.

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

znajdzie groovy pliki nie w docelowej ścieżce katalogu.

Scott M Gardner
źródło
3

Aby rozwiązać ten problem, możesz po prostu użyć tego warunku znajdowania:

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

Możesz dodać więcej takich ograniczeń:

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

Więcej informacji na ten temat można znaleźć w sekcji strony podręcznika „Operatorzy”: http://unixhelp.ed.ac.uk/CGI/man-cgi?find

Źródło kodu
źródło
3

Pamiętaj, że jeśli to zrobisz

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

wówczas -printjest implikowane, gdy całe wyrażenie ( -type f -name 'messages.*') jest prawdziwe, ponieważ nie ma „akcji” (jak -exec).

Chociaż, aby przestać schodzić do niektórych katalogów, powinieneś używać wszystkiego, co pasuje do tych katalogów, i śledzić je -prune(co ma na celu zatrzymać schodzenie do katalogów); tak:

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

Wartość ta ma wartość True dla katalogów .svn i możemy użyć zwarcia logicznego, wykonując to przez -o(OR), po czym to, co następuje po, -ojest sprawdzane tylko wtedy, gdy pierwsza część jest False, a zatem nie jest katalogiem .svn. Innymi słowy, następujące:

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

będzie oceniać tylko to, co jest właściwe -o, mianowicie -name 'message.*' -exec grep -Iw uint {}dla plików NIE znajdujących się w katalogach .svn.

Zauważ, że ponieważ .svnprawdopodobnie zawsze jest to katalog (a nie na przykład plik), aw tym przypadku z pewnością nie pasuje do nazwy „message. *”, Równie dobrze możesz pominąć -type di zrobić:

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

Na koniec zauważ, że jeśli pominiesz jakieś działanie ( -execto działanie), powiedz tak:

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

wtedy -printdziałanie jest sugerowane, ale będzie miało zastosowanie do CAŁEGO wyrażenia, w tym -name '.svn' -prune -oczęści, i w ten sposób wydrukuje wszystkie katalogi .svn, a także pliki „message. *”, co prawdopodobnie nie jest tym, czego chcesz. Dlatego zawsze używaj „akcji” po prawej stronie wyrażenia boolowskiego, gdy używasz -prunew ten sposób. A kiedy to działanie jest drukowane, musisz je jawnie dodać, tak:

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

Carlo Wood
źródło
2

Wypróbuj findrepo, które jest prostym narzędziem do znajdowania / grep i znacznie szybszym niż ack Użyłbyś go w tym przypadku:

findrepo uint 'messages.*'
pixelbeat
źródło
2

wcfind to skrypt otoki znalezienia, którego używam do automatycznego usuwania katalogów .svn.

leedm777
źródło
1

Działa to dla mnie w wierszu poleceń systemu Unix

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

Powyższe polecenie wyświetli PLIKI, które nie są w .svn i wykona grep, o którym wspomniałeś.

Felix
źródło
czy „gfind” jest literówką? Nie mam go na Ubuntu 14.04.
Jonathan Hartley,
Zakładając, że miałeś na myśli „znajdź”, to nie do końca działa. Filtruje również takie pliki xxx.svnxxx. Jest to ważne - na przykład, jeśli używasz git zamiast svn, często będziesz chciał dołączyć pliki takie jak .gitignore (które nie są metadanymi, to zwykły plik zawarty w repozytorium) w wynikach wyszukiwania.
Jonathan Hartley,
1

zwykle przesyłam wyjście przez grep jeszcze raz usuwając .svn, w moim zastosowaniu nie jest on dużo wolniejszy. typowy przykład:

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

LUB

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'
geminiimatt
źródło