MC, 2011
Ilustracja do artykułu: Linux find, locate - Wyszukiwanie plików

Linux find, locate - Wyszukiwanie plików

Zagadnienie wyszukiwania plików na Linuksie było dla mnie dość problematyczne na samym początku moich kontaktów z tym systemem. Głównie za sprawą nie najlepszych możliwości, jakie daje pod tym względem program Nautilus. Jak zwykle jednak okazało się, że terminal jest niezastąpiony.

Wyszukiwanie plików po ich nazwie

Do wyszukiwania plików znajdujących się na dysku, ze względu na ich nazwę, służy polecenie locate. Każdorazowe przelatywanie po wszystkich dostępnych plikach i sprawdzanie, czy nazwa pasuje do zadanego przez nas wzorca, byłoby bardzo niewydajne, dlatego polecenie locate korzysta ze swojej poindeksowanej bazy danych. Jest to bardzo ważna informacja, ponieważ jeśli baza będzie nieaktualna, to może nam się nie udać znaleźć pożądanych plików, nawet jeśli faktycznie znajdują się na naszym dysku. Dlatego ważną rzeczą jest zadbanie o aktualne informacje o plikach przed użyciem locate. Do zaktualizowania bazy danych z nazwami plików służy komenda updatedb. Ja aktualizuję tę bazę po każdej dłuższej przerwie w wyszukiwaniu plików. Przykładowe zastosowanie:
root@mateusz:/home/mateusz/Pulpit# updatedb
root@mateusz:/home/mateusz/Pulpit# locate *plik
/home/mateusz/Pulpit/nowy plik
/home/mateusz/Pulpit/plik
/home/mateusz/Pulpit/plik.html

Oczywiście możemy stosować wyrażenia regularne do określenia wzorca poszukiwanej nazwy pliku. Poniżej dołączam wylistowaną pomoc do programu locate, gdzie znajdziemy opis jego dodatkowych możliwości:

root@mateusz:/home/mateusz/Pulpit# locate --help
Użycie: locate [OPCJA]... [WZÓR]...
Wyszukuje wpisy w bazie danych mlocate.

  -b, --basename         dopasowuje tylko podstawowe nazwy ścieżek
  -c, --count            wyświetla tylko liczbę znalezionych wpisów
  -d, --database ŚCIEŻKA DO BAZY DANYCH  używa ŚCIEŻKI DO BAZY DANYCH
                         zamiast domyślnej bazy danych (/var/lib/mlocate/mlocate.db)
  -e, --existing         wyświetla tylko wpisy dla obecnie istniejących
                         plików
  -L, --follow           podąża za dowiązaniami symbolicznymi podczas
                         sprawdzania istnienia plików (domyślnie)
  -h, --help             wyświetla tę pomoc
  -i, --ignore-case      ignoruje różnice znaków podczas dopasowywania
                         wzorów
  -l, --limit, -n OGRANICZENIE  ograniczenie wyjścia (lub liczenia) do
                         OGRANICZENIA wpisów
  -m, --mmap             ignorowane, dla zgodności wstecznej
  -P, --nofollow, -H     nie podąża za dowiązaniami symbolicznymi podczas
                         sprawdzania istnienia pliku
  -0, --null             oddziela wpisy za pomocą NULL na wyjściu
  -S, --statistics       nie wyszukuje wpisów, wyświetla statystyki o
                         każdej używanej bazie danych
  -q, --quiet            nie zgłasza komunikatów błędów podczas
                         odczytywania baz danych
  -r, --regexp WYRAŻENIE REGULARNE  wyszukuje podstawowe WYRAŻENIE
                         REGULARNE zamiast wzorów
      --regex            wzory to rozszerzone wyrażenia regularne
  -s, --stdio            ignorowane, dla zgodności wstecznej
  -V, --version          wyświetla informację o wersji
  -w, --wholename        dopasowuje całą nazwę (domyślnie)

Proszę zgłaszać błędy do mitr@redhat.com.

Można podejść do tego inaczej?

Zdarza mi się stosować również dwa inne sposoby na wyszukiwanie plików ze względu na ich nazwę, które są szczególnie przydatne przy przeszukiwaniu zewnętrznych nośników danych. Pierwszym z nich jest komenda find. Wystarczy przejść w terminalu do interesującego nas urządzenia, a następnie wydać polecenie:
find ścieżka katalogu nadrzędnego -name wzorzec nazwy
Na przykład spróbujmy znaleźć wszystkie pliki o rozszerzeniu .html, jakie mamy w systemie:
find / -name *.html

Drugi sposób to połączenie poleceń ls i grep:

ls -R | grep "wzorzec"
Dla przykładu, gdy chcemy znaleźć pliki o danym rozszerzeniu .jpg:
ls -R | grep ".jpg"

Wyszukiwanie plików ze względu na ich zawartość

Do wyszukiwania plików ze względu na ich zawartość używam polecenia grep. Generalnie, jest to naprawdę potężne narzędzie, które wyszukuje zadanych wzorców we wskazanych plikach lub strumieniu wejściowym. Można go używać na dziesiątki sposobów, do dziesiątek przypadków, ja jednak chciałbym pokazać, jak używam go do wyszukiwania plików zawierających dane wyrażenie, bądź takich, które właśnie danego wyrażenia nie zawierają.
root@mateusz:/home/mateusz/Pulpit/test# grep "mblog.boo" *
plik3:www.mblog.boo.pl
Jak widać, wyświetlona nam została nazwa pliku wraz z całym wersem, w którym znalazła się szukana fraza. Jeżeli interesują nas tylko i wyłącznie nazwy szukanych plików, należy dodać parametr -l.
root@mateusz:/home/mateusz/Pulpit/test# grep -l "mblog.boo" *
plik3
Zdarza mi się również poszukiwać plików, które nie zawierają danego wzorca. Zwykłem wykorzystywać w tym celu parametr -L.
root@mateusz:/home/mateusz/Pulpit/test# grep -L "mblog.boo" *
plik1
plik2
plik4
plik5

Mam świadomość, że często problem poszukiwania plików po ich zawartości, może być bardziej złożony, dlatego bardzo gorąco zachęcam do bliższego zapoznania się z możliwościami programu grep.

root@mateusz:/home/mateusz/Pulpit/test# grep --help
Składnia: grep [OPCJA]... WZORZEC [PLIK] ...
Szukanie WZORCA w każdym PLIKU lub na standardowym wejściu
WZORZEC domyślnie jest podstawowym wyrażeniem regularnym (BRE).
Przykład: grep -i 'hello world' menu.h main.c

Wybór i interpretacja wyrażeń regularnych:
  -E, --extended-regexp     WZORZEC jest rozszerzonym wyr. regularnym (ERE)
  -F, --fixed-strings       WZORZEC napisy oddzielone przez zn. nowej linii
  -G, --basic-regexp        WZORZEC jest podstawowym wyr. regularnym (BRE)
  -P, --perl-regexp         WZORZEC jest wyrażeniem regularnym perla
  -e, --regexp=WZORZEC      użycie WZORCA jako wyrażenia regularnego
  -f, --file=PLIK           użycie wzorców z PLIKU
  -i, --ignore-case         zignorowanie rożnic między małymi i wlk. lit.
  -w, --word-regexp         dopasowanie WZORCA tylko do pełnych słów
  -x, --line-regexp         dopasowanie WZORCA tylko do całych linii
  -z, --null-data           linie są zakończone bajtem 0, nie znakiem
                            nowej linii

Różne:
  -s, --no-messages         bez komunikatów o błędach
  -v, --invert-match        wybierz linie nie pasujące
  -V, --version             wypisz informację o wersji i zakończ
      --help                wyświetl tę informację i zakończ
      --mmap                jeżeli możliwe mapuj pliki w pamięci

Sterowanie danymi wyjściowymi:
  -m, --max-count=ILE       zatrzymanie po ILU dopasowaniach
  -b, --byte-offset         wypisanie pozycji bajtów w wyniku
  -n, --line-number         wypisanie numerów linii w wyniku
      --line-buffered       opróżnienie bufora po każdej linii
  -H, --with-filename       wypisanie nazwy pliku dla każdej linii
  -h, --no-filename         bez nazwy pliku w liniach wyjściowych
      --label=ETYKIETA      w wyniku ETYKIETA zastępuje nazwe pliku
  -o, --only-matching       pokazanie tylko kawałka, który pasuje do WZORCA
  -q, --quiet, --silent     wyłączenie wypisywanie wyniku
      --binary-files=TYP    założenie, że pliki binarne są typu TYP
                            TYP to 'binary', 'text' lub 'without-match'.
  -a, --text                równoważne --binary-files=text
  -I                        równoważne --binary-files=without-match
  -d, --directories=DZIAŁANIE  jak się obchodzić z katalogami,
                            DZIAŁANIE to `read' (czytanie), `recurse'
                            (przeglądanie rekurencujne) albo 'skip'
                            (pominięcie).
  -D, --devices=DZIAŁANIE   jak odwoływać się do urządzeń, FIFO i gniazd,
                            DZIAŁANIE to 'read' (czytaj) albo 'skip' (pomiń)
  -R, -r, --recursive       równoważne --directories=recurse .
      --include=WZORZEC     przeszukiwane będą pliki pasujące do WZORCA
      --exclude=WZORZEC     pliki pasujące do WZORCA będą pominięte
      --exclude-from=PLIK   pominięcie plików pasujących do WZORCÓW w PLIKU
      --exclude-dir=WZORZEC  katalogi pasujące do WZORCA będą pominięte
  -L, --files-without-match  wypisanie tylko nazw PLIKÓW bez trafień
  -l, --files-with-matches  wypisanie tylko nazw PLIKÓW z trafieniami
  -c, --count               wypisanie tylko liczby pasujących linii w PLIKACH
  -T, --initial-tab         wyrównanie linii przez TAB (jeżeli potrzebne)
  -Z, --null                wypisanie bajtu 0 po każdej nazwie PLIKU

Sterowanie kontekstem:
  -B, --before-context=ILE  wypisanie ILU linii kontekstu przed
  -A, --after-context=ILE   wypisanie ILU linii kontekstu po
  -C, --context=ILE         wypisanie ILU linii kontekstu
  -ILE                      to samo co --context=ILE
      --color[=KIEDY],
      --colour[=KIEDY]      oznaczanie pasujących znaków,
                            KIEDY to `always' (zawsze), `never' (nigdy)
                            albo `auto' (automatycznie).
  -U, --binary              bez usuwania znaków nowej linii na końcu
  -u, --unix-byte-offsets   podawanie pozycji tak jakby nie było CRów (MSDOS)

`egrep' oznacza `grep -E'. `fgrep' oznacza `grep -F'.
Używanie nazw `egrep' i `fgrep' jest przestarzałe.
Bez podanie PLIKU albo gdy PLIK to -, czytane jest standardowe wejście.
Jeżeli podano mniej niż dwa PLIKI, zakłada -h. Zakończenie z kodem 0
jeżeli WZORZEC pasuje, z 1, jeżeli nie, z 2, jeżeli są problemy.

Raporty o błędach należy wysyłać do bug-grep@gnu.org
Strona domowa Grepa GNU: http://www.gnu.org/software/grep/
Pomoc w używaniu oprogramowania GNU: http://www.gnu.org/gethelp/

Komentarze (4)

Imię:
Treść:
Administrator 2020-07-10 06:56:35
@Rafal, dziękuję za uwagę - poprawione.
Rafał 2020-07-09 10:18:56
Poprawcie proszę w przykładach komendę ls - R na ls -R
Administrator 2017-05-24 08:07:35
@Policjant, cieszę się, że artykuł przypadł do gustu. Pozdrawiam.
Policjant 2017-05-23 16:49:11
Bardzo czytelnie i na temat