Szybsze alternatywy dla „znajdź” i „zlokalizuj”?

22

Chciałbym użyć „znajdź” i zlokalizuj ”do wyszukiwania plików źródłowych w moim projekcie, ale ich uruchomienie zajmuje dużo czasu. Czy są szybsze alternatywy dla tych programów, o których nie wiem, lub sposoby na przyspieszenie wydajności tych programów?

benhsu
źródło
2
locatepowinien już być dość szybki, biorąc pod uwagę, że korzysta z gotowego indeksu (głównym zastrzeżeniem jest to, że musi być aktualizowany), podczas gdy findmusi czytać katalogi.
afrazier
2
Z której lokalizacji korzystasz? mlocate jest znacznie szybszy niż slocate (zwróć uwagę, że którykolwiek pakiet, który zainstalowałeś, polecenie jest nadal zlokalizowane, więc sprawdź menedżera pakietów)
Paul
@ benhsu, kiedy uruchamiam find /usr/src -name fprintf.cna komputerze stacjonarnym OpenBSD, zwraca lokalizację tych plików źródłowych w mniej niż 10 sekund. locate fprintf.c | grep '^/usr/src.*/fprintf.c$'wraca w niecałą sekundę. Jaka jest twoja definicja „długi czas uruchamiania” i jak można wykorzystać findi locate?
Kusalananda
@Paul, używam mlocate.
benhsu
@KAK, chciałbym użyć danych wyjściowych find / locate do otwarcia pliku w emacsie. mam na myśli przypadek użycia: chcę edytować plik, wpisuję nazwę pliku (lub kilka wyrażeń regularnych pasujących do nazwy pliku) do emacs, a emacs użyje find / locate, aby wyświetlić listę pasujących plików, więc podoba mi się czas reakcji wystarczająco szybki, aby być interaktywnym (poniżej 1 sekundy). W $ HOME mam około 3 milionów plików, jedną rzeczą, którą mogę zrobić, jest wycięcie niektórych plików z polecenia find.
benhsu

Odpowiedzi:

16

Wyszukiwanie plików źródłowych w projekcie

Użyj prostszego polecenia

Ogólnie rzecz biorąc, źródło projektu prawdopodobnie znajduje się w jednym miejscu, być może w kilku podkatalogach zagnieżdżonych nie więcej niż dwa lub trzy głębokie, więc możesz użyć (prawdopodobnie) szybszego polecenia, takiego jak

(cd /path/to/project; ls *.c */*.c */*/*.c)

Skorzystaj z metadanych projektu

W projekcie C zazwyczaj masz plik Makefile. W innych projektach możesz mieć coś podobnego. Mogą to być szybki sposób na wyodrębnienie listy plików (i ich lokalizacji), napisanie skryptu, który wykorzystuje te informacje do zlokalizowania plików. Mam skrypt „źródeł”, dzięki czemu mogę pisać polecenia takie jak grep variable $(sources programname).

Przyspieszenie wyszukiwania

Wyszukaj mniej miejsc, zamiast find / …używać find /path/to/project …tam, gdzie to możliwe. Uprość kryteria wyboru w jak największym stopniu. Użyj potoków, aby odroczyć niektóre kryteria wyboru, jeśli jest to bardziej wydajne.

Możesz także ograniczyć głębokość wyszukiwania. Dla mnie to znacznie poprawia szybkość „znajdowania”. Możesz użyć przełącznika -maxdepth. Na przykład „-maxdepth 5”

Przyspieszenie zlokalizować

Upewnij się, że indeksuje lokalizacje, które Cię interesują. Przeczytaj stronę podręcznika i skorzystaj z opcji odpowiednich dla twojego zadania.

   -U <dir>
          Create slocate database starting at path <dir>.

   -d <path>
          --database=<path> Specifies the path of databases to search  in.


   -l <level>
          Security  level.   0  turns  security checks off. This will make
          searchs faster.   1  turns  security  checks  on.  This  is  the
          default.

Usuń potrzebę wyszukiwania

Może szukasz, bo zapomniałeś, gdzie coś jest lub nie zostało powiedziane. W pierwszym przypadku pisz notatki (dokumentację), w drugim pytaj? Konwencje, standardy i spójność mogą bardzo pomóc.

RedGrittyBrick
źródło
10

Użyłem części „przyspieszenie lokalizacji” odpowiedzi RedGrittyBrick. Utworzyłem mniejszą db:

updatedb -o /home/benhsu/ben.db -U /home/benhsu/ -e "uninteresting/directory1 uninteresting/directory2"

następnie wskazał locatena to:locate -d /home/benhsu/ben.db

benhsu
źródło
6

Taktyką, której używam, jest zastosowanie -maxdepthopcji z find:

find -maxdepth 1 -iname "*target*"

Powtarzaj z coraz większą głębokością, aż znajdziesz to, czego szukasz, lub zmęczysz się szukaniem. Pierwsze kilka iteracji prawdopodobnie powróci natychmiast.

Zapewnia to, że nie marnujesz czasu z góry na przeglądanie głębokich masywnych sub-drzew, gdy bardziej prawdopodobne jest, że to, czego szukasz, będzie blisko podstawy hierarchii.


Oto przykładowy skrypt automatyzujący ten proces (Ctrl-C, gdy zobaczysz, co chcesz):

(
TARGET="*target*"
for i in $(seq 1 9) ; do
   echo "=== search depth: $i"
   find -mindepth $i -maxdepth $i -iname "$TARGET"
done
echo "=== search depth: 10+"
find -mindepth 10 -iname $TARGET
)

Zauważ, że związana z tym nadmiarowość (każde przejście będzie musiało przechodzić przez foldery przetwarzane w poprzednich przebiegach) zostanie w dużej mierze zoptymalizowane poprzez buforowanie dysku.

Dlaczego findta kolejność wyszukiwania nie jest funkcją wbudowaną? Może dlatego, że byłoby to skomplikowane / niemożliwe do wdrożenia, gdyby założyć, że zbędne przejście było niedopuszczalne. Istnienie -depthopcji wskazuje na taką możliwość, ale niestety ...

nobar
źródło
1
... wykonując w ten sposób wyszukiwanie „wszerz”.
nobar
3

Innym łatwym rozwiązaniem jest użycie nowszego rozszerzonego globowania powłoki. Umożliwić:

  • bash: shopt -s globstar
  • ksh: set -o globstar
  • zsh: już włączony

Następnie możesz uruchomić takie polecenia w katalogu źródłowym najwyższego poziomu:

# grep through all c files
grep printf **/*.c

# grep through all files
grep printf ** 2>/dev/null

Ma to tę zaletę, że przeszukuje rekurencyjnie wszystkie podkatalogi i jest bardzo szybkie.

dannyw
źródło
3

Srebrny Poszukiwacz

Może się okazać, że przydaje się ono do bardzo szybkiego wyszukiwania zawartości ogromnej liczby plików kodu źródłowego. Po prostu wpisz ag <keyword>. Oto niektóre z moich wyników apt show silversearcher-ag:

Zwykle używam go z:

-G --file-search-regex PATTERN Przeszukuj tylko pliki, których nazwy pasują do WZORCA.

ag -G "css$" important

zrzut ekranu

Pablo A.
źródło
1
w ripgrep za algorytm jest rzekomo szybciej niż silversearch, a także wyróżnieniem .gitignorepliki i przeskakuje .git, .svn, .hg.. foldery.
ccpizza
@ccpizza So? Silver Searcher.gitignore domyślnie honoruje i ignoruje również pliki ukryte i binarne. Mają także więcej współpracowników, więcej gwiazd na Githubie (14700 vs 8300) i jest już na repozytorium dystrybucji burmistrza. Podaj zaktualizowane wiarygodne porównanie źródeł innych firm. Niemniej jednak ripgrepwygląda świetnie na oprogramowanie.
Pablo A
dobrze wiedzieć! Nie jestem ripgrepw żaden sposób powiązany z autorem (autorami) , to po prostu pasuje do moich wymagań, więc przestałem szukać innych opcji.
ccpizza
Srebrny poszukiwacz .gitignoreteż szanuje . To powiedziawszy, rgjest absolutnie niesamowite. Po pierwsze, ma obsługę Unicode. Z mojego doświadczenia rgkonsekwentnie co najmniej dwa razy szybszego niż ag(YMMV), wydaje mi się, że jest to spowodowane parserem wyrażeń regularnych Rora, który oczywiście nie był jeszcze gotowy w latach, które agbyły nowe. rgmoże dawać deterministyczne dane wyjściowe (ale domyślnie tego nie robi), może umieszczać na czarnej liście typy plików, na których agmoże znajdować się tylko na białej liście, może ignorować pliki na podstawie rozmiaru (dzienniki pa). Nadal używam agna wypadek, gdy potrzebuję dopasowania wieloliniowego, czego rgnie można zrobić.
The Pellmeister
2

Aby znaleźć zamiennik, sprawdź fd . Ma prostszy / bardziej intuicyjny interfejs niż oryginalne polecenie find i jest nieco szybszy.

Keith Hughitt
źródło