Polecenie find w Linuksie: opcje -name, -type, -size, -mtime i -delete
Polecenie find w Linuksie schodzi kolejno w dół od folderu startowego i znajduje pliki oraz foldery spełniające warunki takie jak nazwa, rodzaj, rozmiar, czas modyfikacji i uprawnienia. Po utworzeniu dziesięciu plików w folderze testowym na serwerze AlmaLinux 9 i uruchamianiu polecenia ze zmianą jednego warunku naraz znalezione pliki przekazano przez -exec do innych poleceń, a przy usuwaniu najpierw sprawdzano listę z tymi samymi warunkami, zanim użyto -delete.
Ścieżki folderu testowego i czasy plików w polach wyników zmieniono na przykładowe wartości. W danych z serwera Debian 12 przykładowa jest tylko ścieżka folderu domowego, a reszta pozostała bez zmian.
1️⃣ Jak używać polecenia find w Linuksie
Podstawowa forma to [find ścieżka-startowa warunki]. Bez ścieżki startowej szuka w bieżącym folderze (.), a bez warunków wypisuje wszystkie pliki i foldery pod ścieżką startową.
Test przeprowadzono w /root/work z trzema folderami i dziesięcioma plikami, jak poniżej.
find /root/work/root/work
/root/work/docs
/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/backup
/root/work/report.txt
/root/work/README.md
/root/work/run.sh
/root/work/my notes.txt
/root/work/empty.txtfind nie sortuje wyników według nazwy; w tym uruchomieniu po dojściu do folderu docs najpierw wypisał wszystkie pliki w środku, a potem przeszedł do logs.
Gdy zapiszesz kilka warunków z rzędu, zostaną tylko pliki spełniające wszystkie.
-name porównuje ze wzorcem tylko nazwę pliku, a nie ścieżkę. Ujmij wzorzec w pojedyncze cudzysłowy, aby powłoka nie rozwinęła najpierw * i przekazała go do find bez zmian.
find /root/work -name '*.txt'/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/report.txt
/root/work/my notes.txt
/root/work/empty.txt-name rozróżnia wielkość liter. Szukanie nazw zaczynających się od readme dało tylko docs/readme.txt, a -iname także README.md.
find /root/work -name 'readme*'/root/work/docs/readme.txtfind /root/work -iname 'readme*'/root/work/docs/readme.txt
/root/work/README.mdfind znajduje się w pakiecie findutils. Wersja z pierwszego wiersza [find --version] to findutils 4.8 na serwerze AlmaLinux 9.8 i 4.9 na serwerze Debian 12.
2️⃣ find -type d i -maxdepth
-type f zostawia tylko zwykłe pliki, a -type d tylko foldery.
find /root/work -type d/root/work
/root/work/docs
/root/work/logs
/root/work/backupŚcieżka startowa /root/work też jest folderem, więc pojawiła się w pierwszym wierszu. Po zmianie na -type f w tej samej ścieżce pojawiło się wszystkie dziesięć plików.
-maxdepth ustala, o ile poziomów zejść od ścieżki startowej. Z -maxdepth 1 pliki z docs i logs odpadły, a zostało pięć plików tuż pod /root/work.
find /root/work -maxdepth 1 -type f/root/work/report.txt
/root/work/README.md
/root/work/run.sh
/root/work/my notes.txt
/root/work/empty.txtZ kolei -mindepth 2 pominęło to, co leży tuż pod ścieżką startową, i wypisało tylko pięć plików w podfolderach.
find /root/work -mindepth 2 -type f/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmpStrona man zaleca wpisywanie opcji globalnych, takich jak -maxdepth, tuż za ścieżką startową. -maxdepth 1 za -type f też dało te same pięć plików, ale w terminalu pojawia się wiersz ostrzeżenia, by opcje globalne wpisywać wcześniej (według strony man).
Aby sprawdzić tylko liczbę folderów lub plików, przekaż dane wyjściowe do wc -l. Zliczenie wyniku -type d dało 4 razem ze ścieżką startową.
find /root/work -type d | wc -l4Z -maxdepth 1 także wyszło 4, bo wszystkie trzy podfoldery leżą tuż pod ścieżką startową.
find /root/work -maxdepth 1 -type d | wc -l4Zliczenie przez -mindepth 2 tylko plików w podfolderach dało 5.
find /root/work -mindepth 2 -type f | wc -l53️⃣ Warunki rozmiaru i czasu polecenia find
+ przed liczbą oznacza więcej niż ta wartość, - mniej, a bez znaku dokładnie tę wartość. Jednostki -size są w tabeli poniżej (według strony man).
| Jednostka | Rozmiar | Tak |
|---|---|---|
| c | 1 bajt | -size +500c |
| k | 1,024 bajty | -size +1k |
| M | 1,048,576 bajtów | -size +1M |
| G | 1,073,741,824 bajty | -size +1G |
| (brak) | Bloki 512-bajtowe | -size +2 |
find /root/work -type f -size +1k/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txtPliki większe niż 1k to guide.txt z 5,000 bajtów, app.log z 2MB i report.txt z 1,200 bajtów.
find /root/work -size +1M/root/work/logs/app.logPo dwukrotnym wpisaniu -size jako zakresu zostały tylko dwa pliki większe niż 1k i mniejsze niż 100k.
find /root/work -type f -size +1k -size -100k/root/work/docs/guide.txt
/root/work/report.txt-size dzieli rozmiar przez jednostkę i zaokrągla w górę przed porównaniem. Dlatego README.md z 300 bajtami też liczy się jako 1k, a przy -size -1k pojawił się tylko empty.txt o rozmiarze 0.
find /root/work -type f -size -1k/root/work/empty.txtAby sprawdzić warunki czasu, ustawiono czas modyfikacji README.md, my notes.txt i docs/readme.txt na 3 dni temu, a dwóch plików .tmp na 10 dni temu. Każdy plik ma trzy czasy: dostępu, modyfikacji i zmiany, które sprawdzisz przez polecenie stat.
-mtime liczy czas od ostatniej modyfikacji w jednostkach 24-godzinnych. Przy -mtime -1 pojawiło się pięć plików utworzonych w ciągu 24 godzin.
find /root/work -type f -mtime -1/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txtPrzy -mtime +7 pojawiły się tylko dwa pliki .tmp ustawione na 10 dni temu. Tej formy używaj do sprawdzenia listy przed usunięciem starych dzienników lub plików tymczasowych.
find /root/work -type f -mtime +7/root/work/docs/old.tmp
/root/work/logs/cache.tmp-mmin liczy tak samo w minutach. Wynik -mmin -60 to te same pięć plików co przy -mtime -1.
find /root/work -type f -mmin -60/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txt-newer znajduje pliki zmodyfikowane później niż plik odniesienia. Z README.md ustawionym na 3 dni temu jako odniesieniem pojawiło się pięć plików utworzonych później.
find /root/work -type f -newer /root/work/README.md/root/work/docs/guide.txt
/root/work/logs/app.log
/root/work/report.txt
/root/work/run.sh
/root/work/empty.txt-empty znajduje naraz pliki o rozmiarze 0 i puste foldery, więc pojawiły się pusty folder backup i empty.txt.
find /root/work -empty/root/work/backup
/root/work/empty.txt4️⃣ Warunki -perm i -user polecenia find
Gdy po -perm wpiszesz samą liczbę, szuka plików o dokładnie takich uprawnieniach. Przy -perm 644 odpadły run.sh z 755 i my notes.txt z 600, a pojawiło się osiem plików.
find /root/work -type f -perm 644/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/report.txt
/root/work/README.md
/root/work/empty.txtZ - przed trybem szuka plików mających wszystkie podane uprawnienia. Uprawnienie wykonania właściciela (u+x) miał tylko run.sh.
find /root/work -type f -perm -u+x/root/work/run.shZ / przed trybem wystarczy jedno z podanych uprawnień. 6000 to suma SUID (4000) i SGID (2000), a tej formy używa się do kontroli na serwerze plików, które po uruchomieniu działają z uprawnieniami właściciela lub grupy.
W folderze testowym takich plików nie było, więc po nadaniu SUID plikowi run.sh pojawił się run.sh.
chmod u+s /root/work/run.shfind /root/work -type f -perm /6000/root/work/run.shW starszych materiałach w tym miejscu widnieje -perm +6000. Uruchomienie tego wprost skończyło się błędem [invalid mode].
find /root/work -type f -perm +6000find: invalid mode '+6000'Forma + została usunięta w findutils 4.5.12 (według strony man), więc wpisuj /. SUID nadany do testu usunięto przez chmod u-s.
-user filtruje według nazwy właściciela. Wszystkie pliki testowe należą do root, więc samo -user root niczego nie odfiltrowuje; po dodaniu -name dla plików .log został tylko app.log.
find /root/work -type f -user root -name '*.log'/root/work/logs/app.log-nouser znajduje pliki, których UID właściciela nie ma konta. Służy do kontroli plików pozostałych na serwerze po usunięciu konta; po zmianie właściciela guide.txt na nieistniejący UID 1500 pojawił się guide.txt.
chown 1500:1500 /root/work/docs/guide.txtfind /root/work -nouser/root/work/docs/guide.txt-nogroup robi to samo dla grupy i pojawił się guide.txt, któremu grupę też zmieniono na 1500. Po teście przywrócono to przez chown root:root.
Z -o między warunkami wystarczy jeden z nich. Razem z innym warunkiem, takim jak -type f, ujmij warunki połączone przez -o w nawiasy. Przed nawiasami wstaw ukośnik wsteczny, aby powłoka nie zinterpretowała ich pierwsza, a między nawiasami i warunkami zostaw spacje.
find /root/work -type f \( -name '*.log' -o -name '*.tmp' \)/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp! odwraca warunek stojący tuż za nim. Szukanie plików innych niż .txt dało pięć.
find /root/work -type f ! -name '*.txt'/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmp
/root/work/README.md
/root/work/run.sh5️⃣ Użycie find -exec
-exec uruchamia polecenie wpisane za nim dla każdego znalezionego pliku, a znaleziona ścieżka trafia w miejsce {}. Średnik na końcu polecenia zapisuje się jako \;, aby powłoka nie odczytała go najpierw jako separatora poleceń.
find /root/work -name '*.log' -exec ls -l {} \;-rw-r--r-- 1 root root 2097152 Oct 5 14:10 /root/work/logs/app.logGdy zakończysz + zamiast \;, znalezione ścieżki zostaną zebrane, a polecenie uruchomi się tylko raz. W porównaniu przez echo \; wypisało pięć ścieżek w pięciu wierszach, a + w jednym.
find /root/work -name '*.txt' -exec echo {} \;/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/report.txt
/root/work/my notes.txt
/root/work/empty.txtfind /root/work -name '*.txt' -exec echo {} +/root/work/docs/readme.txt /root/work/docs/guide.txt /root/work/report.txt /root/work/my notes.txt /root/work/empty.txtPolecenia przyjmujące wiele ścieżek, jak ls, grupuj przez +, aby ograniczyć liczbę uruchomień. Rozmiar trzech plików większych niż 1k sprawdzono jednym ls -lh.
find /root/work -type f -size +1k -exec ls -lh {} +-rw-r--r-- 1 root root 4.9K Oct 5 14:10 /root/work/docs/guide.txt
-rw-r--r-- 1 root root 2.0M Oct 5 14:10 /root/work/logs/app.log
-rw-r--r-- 1 root root 1.2K Oct 5 14:10 /root/work/report.txt-exec służy też do masowego ustawiania uprawnień folderu WWW: 644 dla plików i 755 dla folderów. Przed uruchomieniem wyszukano pliki z inną wartością i pojawiły się run.sh oraz my notes.txt.
find /root/work -type f ! -perm 644/root/work/run.sh
/root/work/my notes.txtPliki i foldery mają różne uprawnienia, więc uruchamiaj osobno -type f i -type d. chmod też przyjmuje wiele ścieżek, dlatego zakończono na +.
find /root/work -type f -exec chmod 644 {} +find /root/work -type d -exec chmod 755 {} +Ponowne szukanie z tym samym warunkiem nic nie dało, a folder backup, wcześniej ustawiony na 700, także miał 755.
Jednak run.sh też zmienił się na 644 i po uruchomieniu pojawiło się [Permission denied]. W folderach z plikami wykonywalnymi przywróć im uprawnienie wykonania przez chmod +x.
Aby zmienić tylko pliki w podfolderach, dodaj -mindepth 2. Z 660 zmieniło się tylko pięć plików w docs i logs, a po sprawdzeniu przywrócono 644.
find /root/work -mindepth 2 -type f -exec chmod 660 {} +find /root/work -type f -perm 660/root/work/docs/readme.txt
/root/work/docs/guide.txt
/root/work/docs/old.tmp
/root/work/logs/app.log
/root/work/logs/cache.tmpPołączenie find i grep pozwala szukać po zawartości pliku, a nie po nazwie. Aby odtworzyć kontrolę webshelli, w osobnym folderze /root/site utworzono cztery pliki PHP, a do html-cache.php i photo.php w folderze upload wstawiono tekst [base64_decode].
find /root/site -type f/root/site/lib/func.php
/root/site/upload/html-cache.php
/root/site/upload/photo.php
/root/site/index.phpGdy znasz nazwę webshella, szukaj przez -name. Po dodaniu -maxdepth 2, by zejść tylko do folderu upload, pojawił się sam html-cache.php.
find /root/site -maxdepth 2 -type f -name 'html*.php'/root/site/upload/html-cache.phpphoto.php o zwyczajnej nazwie tu się nie pojawił. grep -l uruchomiony przez -exec wypisuje tylko ścieżki plików z tekstem i pojawiły się oba pliki.
find /root/site -name '*.php' -exec grep -l 'base64_decode' {} +/root/site/upload/html-cache.php
/root/site/upload/photo.php[base64_decode] to funkcja obecna także w plikach rdzenia WordPressa, więc znalezione pliki otwórz i sprawdź ich zawartość przed usunięciem.
-print0 wstawia między ścieżki znak null zamiast znaku nowego wiersza. Znak null nie jest widoczny na ekranie, więc ścieżki wyszły sklejone w jednym wierszu.
find /root/work -name '*.txt' -print0/root/work/docs/readme.txt/root/work/docs/guide.txt/root/work/report.txt/root/work/my notes.txt/root/work/empty.txtAby przekazać do innego polecenia bez rozbijania także nazwy ze spacjami, jak my notes.txt, dane wyjściowe -print0 łączy się z xargs -0 (według strony man).
6️⃣ Usuwanie plików przez find i opcje
Przed usunięciem najpierw uruchom te same warunki bez usuwania i sprawdź wzrokiem listę plików do usunięcia.
find /root/work -name '*.tmp'/root/work/docs/old.tmp
/root/work/logs/cache.tmp-exec rm {} \; uruchamia rm dla każdego znalezionego pliku. Uruchomione tylko w folderze logs usunęło cache.tmp i został sam app.log.
find /root/work/logs -name '*.tmp' -exec rm {} \;ls /root/work/logsapp.log-delete sprawia, że find usuwa bezpośrednio, bez uruchamiania rm. Po uruchomieniu nic nie wypisało, a ponowne szukanie z tym samym warunkiem nie znalazło już plików .tmp.
find /root/work -name '*.tmp' -deletefind /root/work -name '*.tmp'-delete musi zawsze stać za warunkami. find oblicza wiersz polecenia od początku jako jedno wyrażenie, więc z -delete na początku próbuje usunąć wszystko pod ścieżką startową, zanim spojrzy na warunki (według strony man).
🔲 Opcje polecenia find
📌 Główne opcje: wyniki z tego artykułu
| Opcja | Zadanie | Wynik w tym artykule | |
|---|---|---|---|
| -name | Znajduje nazwy pasujące do wzorca (rozróżnia wielkość liter) | '*.txt' daje pięć plików, 'readme*' tylko docs/readme.txt | |
| -iname | Porównuje nazwy bez rozróżniania wielkości liter | 'readme*' daje docs/readme.txt i README.md | |
| -type f, -type d | Zostawia tylko zwykłe pliki (f) lub foldery (d) | -type d daje cztery foldery ze ścieżką startową, -type f dziesięć plików | |
| -maxdepth | Schodzi tylko N poziomów pod ścieżkę startową | -maxdepth 1 zostawia tylko pięć plików tuż pod /root/work | |
| -mindepth | Pomija poziomy powyżej N od ścieżki startowej | -mindepth 2 daje tylko pięć plików w podfolderach | |
| -size | Szuka według rozmiaru (+ większe, - mniejsze, jednostki c, k, M, G) | -size +1k daje trzy pliki, -size -1k tylko empty.txt | |
| -mtime | Porównuje czas od modyfikacji zawartości w jednostkach 24-godzinnych | -mtime -1 daje pięć plików, -mtime +7 dwa pliki .tmp | |
| -mmin | Porównuje czas od modyfikacji w minutach | -mmin -60 daje te same pięć plików co -mtime -1 | |
| -ctime | Porównuje w jednostkach 24-godzinnych aż do zmiany danych pliku, takich jak uprawnienia i nazwa | -ctime -1 daje wszystkie dziesięć plików testowych | |
| -newer | Znajduje to, co zmodyfikowano później niż plik odniesienia | Pięć plików z README.md ustawionym na 3 dni temu jako odniesieniem | |
| -empty | Znajduje pliki o rozmiarze 0 i puste foldery | Daje pusty folder backup i empty.txt | |
| -perm | Szuka według uprawnień (sama liczba: dokładnie ta wartość, - przed: wszystkie podane, / przed: choć jedno) | -perm 644 daje osiem plików, -perm -u+x daje run.sh, a po SUID -perm /6000 daje run.sh | |
| -user | Filtruje według nazwy właściciela | Z -name '*.log' daje app.log, nieistniejące konto kończy się błędem | |
| -nouser | Znajduje to, czego UID właściciela nie ma konta | Daje guide.txt z UID zmienionym na 1500 | |
| -nogroup | Znajduje to, czego GID grupy nie ma grupy | Daje guide.txt z GID zmienionym na 1500 | |
| -o | Zostawia to, co spełnia jeden z warunków (z innymi warunkami w nawiasach) | Grupując .log i .tmp, dostajesz trzy pliki | |
| ! | Odwraca warunek stojący tuż za nim | Daje pięć plików innych niż .txt | |
| -exec | Uruchamia polecenie wpisane za nim dla każdego znalezionego pliku (ścieżka w miejscu {}) | Z + na końcu jedno echo wypisuje pięć ścieżek w jednym wierszu | |
| -print0 | Wstawia między ścieżki znak null zamiast nowego wiersza | Znak null jest niewidoczny, ścieżki są sklejone w jednym wierszu | |
| -delete | find sam usuwa znalezione pliki (stoi za warunkami) | Brak danych wyjściowych, ponowne szukanie nie znalazło plików .tmp |
📎 Pozostałe opcje: według oficjalnego podręcznika
| Opcja | Zadanie | |
|---|---|---|
| -L | Podąża za dowiązaniami symbolicznymi i używa danych pliku docelowego | |
| -path | Porównuje całą ścieżkę zamiast nazwy ze wzorcem powłoki | |
| -regex | Porównuje całą ścieżkę z wyrażeniem regularnym | |
| -iregex | Porównuje jak -regex, bez rozróżniania wielkości liter | |
| -atime | Porównuje czas od ostatniego dostępu w jednostkach 24-godzinnych | |
| -cnewer | Znajduje to, czego stan zmienił się później niż czas modyfikacji pliku odniesienia | |
| -group | Filtruje według nazwy grupy właściciela | |
| -xdev | Nie schodzi do folderów w innych systemach plików | |
| -daystart | Liczy warunki czasu od północy dziś zamiast od 24 godzin wstecz | |
| -prune | Gdy to folder, nie schodzi do niego | |
| -quit | Kończy od razu (-print -quit wypisuje tylko pierwszy wynik) | |
| -printf | Wypisuje w ustalonym przez ciebie formacie | |
| -ls | Wypisuje znalezione pliki w formacie ls -dils | |
| -fprint | Zapisuje znalezione ścieżki we wskazanym pliku zamiast na ekranie | |
| -ok | Działa jak -exec, ale najpierw pyta | |
| -execdir | Działa jak -exec, ale uruchamia polecenie w folderze znalezionego pliku |
🔲 Symulator polecenia find
Symulator poniżej to wirtualny serwer z tym samym folderem testowym, w którym możesz samodzielnie uruchamiać warunki takie jak -name, -type, -size, -mtime i -perm oraz -exec i -delete.
7️⃣ Błędy polecenia find
Gdy wpiszesz wzorzec bez cudzysłowów, powłoka stosuje zasady dla Symbole wieloznaczne i najpierw rozwija go do nazw plików w bieżącym folderze. Po przejściu do folderu docs i wpisaniu *.txt bez cudzysłowów powłoka przekazała dwie nazwy guide.txt i readme.txt i pojawił się poniższy błąd.
cd /root/work/docsfind /root/work -name *.txtfind: paths must precede expression: `readme.txt'
find: possible unquoted pattern after predicate `-name'?Kod wyjścia wyniósł 1.
Bez \; lub + na końcu -exec pojawiło się [missing argument to `-exec’].
find /root/work -name '*.log' -exec ls -l {}find: missing argument to `-exec'Nieistniejąca ścieżka startowa daje [No such file or directory] i kończy się kodem wyjścia 1.
find /nonexistent-dir -name xfind: '/nonexistent-dir': No such file or directoryNieistniejąca nazwa konta w -user albo w -type wartość inna niż ustalone litery, jak f i d, kończą się od razu błędem bez rozpoczęcia szukania.
find /root/work -user nosuchuserfind: 'nosuchuser' is not the name of a known userfind /root/work -type xfind: Unknown argument to -type: xNa zwykłym koncie serwera Debian 12 zmieniono uprawnienia folderu lock w folderze testowym na 000 i przeszukano folder testowy. Nie dało się odczytać lock, pojawiło się [Permission denied], a kod wyjścia wyniósł 1.
find ~/findtest/home/user/findtest
/home/user/findtest/report.txt
/home/user/findtest/lock
find: '/home/user/findtest/lock': Permission denied
/home/user/findtest/docs
/home/user/findtest/docs/readme.txtAby ukryć same wiersze błędów, dodaj 2>/dev/null. Komunikat zniknął, ale kod wyjścia nadal wynosił 1.
find ~/findtest -name '*.txt' 2>/dev/null/home/user/findtest/report.txt
/home/user/findtest/docs/readme.txt🔢 FAQ & polecane treści
Szukanie w treści
Polecenie grep w Linuksie
Artykuł o poleceniu grep, które znajduje tekst w plikach i wypisuje te wiersze, oraz o jego opcjach.
Usuwanie
Polecenie rm w Linuksie: opcje rm -rf i usuwanie bez potwierdzenia
Artykuł o opcjach -r i -f oraz pytaniach potwierdzających polecenia rm przy usuwaniu plików i folderów.
Miejsce na dysku
Polecenie du: sprawdzanie miejsca zajmowanego przez pliki
Artykuł o sumowaniu miejsca na dysku zajmowanego przez foldery i pliki poleceniem du.
ℹ️ Informacja o linkach partnerskich
Treści tej witryny zawierają linki partnerskie. Jeśli odwiedzający kupi produkt lub usługę przez taki link, witryna otrzymuje od sprzedawcy prowizję. Kwota płacona przy tym przez kupującego (podczas promocji spada↓) nie wzrasta. Podane ceny, rabaty i dostępność odnoszą się do chwili pisania i mogą różnić się od stanu faktycznego, dlatego przed zakupem sprawdź je u sprzedawcy. Produkty wybieramy i oceniamy według własnych kryteriów, a prowizja nie wpływa ani na kolejność prezentacji, ani na treść ocen.