Portál AbcLinuxu, 1. května 2025 07:32

Unixové nástroje – 14 (find)

25. 6. 2010 | David Watzke
Články - Unixové nástroje – 14 (find)  

V tomto díle se seznámíme s programem find, který slouží k vyhledávání souborů. Představíme jak standardní verzi, tak GNU rozšíření.

Obsah

find je velice schopný vyhledávací nástroj, který poslouží jak pro jednoduché vyhledávání na základě názvu souboru, tak pro složité hledání na základě dalších údajů a podmínek. Jeho název vychází z anglického slova, které znamená „najít“.

Na GNU/Linuxu se často setkáte s GNU verzí této utility, která rozšiřuje schopnosti programu mimo rozsah standardu.

Standardní verze

link

Základní použití programu vypadá takto:

# vypíše všechny soubory a adresáře v domovském adresáři (rekurzivně)
find ~/

# najde v aktuálním pracovním adresáři všechny soubory a adresáře s názvem končícím na „.pdf“
find -name '*.pdf'

Jak vidíte, pomocí přepínače -name lze vyhledávat soubory na základě (části) jejich názvu. Název adresáře, ve kterém chceme hledat, zadáváme vždy jako první (pokud jej vynecháme, použije se pracovní adresář). Předvedeme si, jak vyhledávat podle jiných kritérií, než je název souboru.

# vyhledá všechny symbolické odkazy v adresáři /tmp
find /tmp -type l

# vyhledá všechny adresáře a soubory s oprávněním 755 v nadřazeném adresáři
find .. -perm 755

# vyhledá všechny soubory patřící uživateli „dave“ a skupině „home“
find -type f -user dave -group home

Jak je vidět na poslední ukázce, kritéria vyhledávání lze kombinovat. Zadáte-li je takto za sebou, find bude hledat položky odpovídající všem kritériím. Jenže co když nám jde o to najít vše kromě položek splňujících dané kritérium? A co když chceme najít soubor, který splňuje buď jedno, anebo jiné kritérium? I toto find zvládá a my si ukážeme jak na to. Přepínač -o představuje logický OR („nebo“), takže stačí, když platí výraz před tímto přepínačem nebo za ním, aby daný soubor odpovídal kritériím vyhledávání.

# vyhledá adresáře, které mají oprávnění 777 nebo patří uživateli „dave“ (nebo splňují obě podmínky)
find -type d -perm 777 -o -user dave

# vyhledá vše kromě obyčejných souborů
find ! -type f

# vyhledá soubory, které patří uživateli „dave“, a zároveň „adresáře“ s oprávněním 775 a skupinou jinou než „home“
find '(' -type f -user dave ')' -o \( -type d -perm 775 ! -group home \)

# najde soubory s příponou .pdf či .ps
find -type f -name '*.pdf' -o -name '*.ps'

Na ukázce jsem předvedl, že je možné používat i priority (závorky), které známe z matematiky nebo programování. Je však nutné je escapovat přidáním zpětného lomítka před závorku nebo je umístit mezi uvozovky či apostrofy. Je to nutné z toho důvodu, že jinak by shell interpretoval závorky po svém, přičemž takto je předá programu. Vykřičník slouží k negaci výrazu.

Teď si předvedeme jeden ze způsobů, jak pro každý nalezený soubor vyhovující daným kritériím spustíme program, kterému předáme název souboru jako argument. Ukázka převede všechny nalezené MP3 soubory na WAV pomocí programu lame.

# vypisuje pouze výstup programu lame
find -type f -name '*.mp3' -exec lame --decode "{}" \;

# lame nic nevypisuje, pouze find vypisuje názvy souborů, když jsou zpracovávány
find -type f -name '*.mp3' -exec lame --decode --silent "{}" + -print

Používá se tedy přepínač -exec, za který napíšeme příkaz, který chceme spustit, i s argumenty, přičemž řetězec {} je před spuštěním nahrazen za název souboru, který by byl jinak právě vypsán na výstup. Konec příkazu značíme středníkem, který musí být escapovaný, jinak by jej shell bral jako ukončení příkazu. V případě, že ukončujeme argumenty hned za uvedením {}, můžeme místo středníku použít znak „+“. V ostatních případech znak plus není nijak zvláštně zpracováván.

Chceme-li být opatrnější, můžeme místo -exec použít -ok, který se před každým spuštěním příkazu nejdříve zeptá, zda jej chcete skutečně spustit. Přepínač -ok nemusí podporovat ukončování pomocí znaku „+“ (např. GNU verze to nepodporuje), proto je lepší používat „;“.

Ukážeme si ještě, jak vyhledávat podle několika dalších kritérií. Nejdříve dle velikosti souborů pomocí přepínače -size.

# hledá soubory větší než 500 bytů (chceme-li vyhledávat v bytech, za číslo přidáme znak "c")
find / -type f -size +500c

# vyhledá soubory velké přesně 2 kB
find .. -type f -size 2048c

# vyhledá soubory menší než 10 MB
find adresář/ -type f -size -10485760c

Vyhledávat lze i podle času poslední změny (pomocí -mtime), času vytvoření (-ctime) a času posledního přístupu k souboru (-atime). Těmto přepínačům předáváme počet dní (od doby spuštění příkazu). Pokud před tento počet dní n připojíme „+“, znamená to „více než n dní“ a opak platí pro „-“, podobně jako u přepínače -size.

# hledá soubory naposledy změněné před více než deseti dny
find -type f -mtime +10

# hledá adresáře vytvořené před méně než dvěma týdny
find -type d -ctime -14

Ještě lze využít přepínač -newer, kterému se předává soubor, jehož čas poslední změny se použije jako referenční pro vyhledávání souborů novějších, než je ten daný.

# hledá soubory a adresáře s časem posledním změny pozdějším, než má „soubor.txt“
find -newer soubor.txt

Chceme-li vyhledat soubory či adresáře, které mají neplatné UID nebo GID (vlastníka či skupinu), použijeme přepínače -nouser a/nebo nogroup.

# vyhledá všechny soubory či adresáře bez platného vlastníka či skupiny
find -nouser -o -nogroup

Měl bych zmínit přepínač -H, který mění chování programu při rekurzivním průchodu adresářů. Bez tohoto přepínače nebo s -L, což je výchozí chování, find nenásleduje symbolické odkazy, přičemž s -H ano. Máte-li tedy adresář, který obsahuje tři soubory a jeden symbolický odkaz na jiný adresář, find -H prohledá i adresář, na který odkaz směřuje.

Běžně se find nejdříve zpracuje explicitně zadaný adresář (nebo „.“, pokud nebyl žádný zadán) a teprve potom teprve jeho obsah. Chceme-li z nějakého důvodu, aby tomu bylo naopak, můžeme použít přepínač -depth.

GNU rozšíření

link

Jak jsem již zmínil, implementace od GNU obsahuje poměrně mnoho rozšíření, které standard neuvádí. Podíváme se na několik z nich.

Často se nám může hodit vyhledávání podle názvu souboru, přičemž nezáleží na velikosti písmen. Toho lze docílit přepínačem -iname.

Chceme-li nalezené položky rovnou mazat, můžeme zadat přepínač -delete.

Pro ovlivnění rekurze lze použít přepínače -mindepth (minimální hloubka) a -maxdepth (maximální hloubka).

# vyhledává pouze v adresáři aktuálním a jeho podadresářích, ale dále nezajde
find -mindepth 1 -maxdepth 2

Přepínač -execdir je podobný jako -exec, ale spouští příkaz z adresáře, ve kterém se nachází daný soubor či adresář.

Chceme-li, aby find vypisoval názvy souborů oddělené znakem NULL (\0), což se hodí některým externím utilitám (například xargs s přepínačem -0), předáme přepínač -print0.

Přepínačem -size lze zadávat velikost v příhodnějších jednotkách, než jsou byty.

# hledá soubory větší než 1 GB
find -type f -size +1G

Komplexnějšího vyhledávání na základě názvů souborů lze docílit použitím regulárních výrazů. Daný výraz zadáme přepínači -regex a typ regulárního výrazu můžeme zvolit přepínačem -regextype.

find toho umí ještě mnohem více, můžete se o tom přesvědčit sami při čtení manuálové stránky.

Seriál Unixové nástroje (dílů: 27)

První díl: Unixové nástroje – 1 (úvod, cat, head, tail), poslední díl: Unixové nástroje – 26 (triky pro práci v Bashi).
Předchozí díl: Unixové nástroje – 13 (ps, kill a signály)
Následující díl: Unixové nástroje – 15 (basename/dirname, test, read)

Související články

Seriál: BASH
Seriál: Nebojíme se kompilace
Regulární výrazy
Bash: chytré doplňování
Barevný a formátovaný text v terminálu

Odkazy a zdroje

man find
Wikipedia: Find

Další články z této rubriky

VDR a DVB-T2, část 2.
VDR a DVB-T2, část 1.
Šifrovaný Proxmox VE 6: ZFS, LUKS, systemd_boot a Dropbear
MapTiler – proměňte obrázek v zoomovatelnou mapu
Syncthing

Diskuse k tomuto článku

25.6.2010 05:36 maslo
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Unix 'find command' helper : http://find.unixpin.com/
25.6.2010 12:05 Andy | skóre: 18 | NMnMet
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
diky
Válka je vůl ... a já taky ;) | Chaotic state of my influence.
25.6.2010 07:08 pht | skóre: 48 | blog: pht
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Název adresáře, ve kterém chceme hledat, zadáváme vždy jako první (pokud jej vynecháme, použije se pracovní adresář).

To vynechání je AFAIK právě GNU rozšíření a pokud nemáte GNU tak bude find kousat. Jinak pointa je v tom, že těch cest může být jedna a více.
find /bin /usr/bin -name find
V případě, že ukončujeme argumenty hned za uvedením {}, můžeme místo středníku použít znak „+“.

Tady by se hodilo říci, že plus mění postup volání programu:
find /bin -exec prog '{}' ';'
=>
prog /bin/bash
prog /bin/cp
...
find /bin -exec prog '{}' '+'
=>
prog /bin/bash /bin/cp ...
Hodilo by se srovnání s -execdir.

Dále by se hodilo vysvětlit co je to -print, -printf a -print0. A že -print je default. To -print0 tam sice máte ale není z toho člověk moc moudrý.
In Ada the typical infinite loop would normally be terminated by detonation.
alblaho avatar 25.6.2010 08:07 alblaho | skóre: 17 | blog: alblog
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Já mám v binu skritp, který se jmenuje sifi (simple find) a vypadá takhle.
#!/bin/sh

find . -name "$1"
Používám ho denně, například:
git add `sifi HlubokoVBalíčcíchPohřbenýSoubor.java`
xdg-open `sifi HlubokoVBalíčcíchPohřbenýSoubor.java`
25.6.2010 10:11 dd
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Perfektne, dik za tip!
25.6.2010 19:57 vencas | skóre: 32
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
No, a já bych v zsh napsal
git add **/HlubokoVBalíčcíchPohřbenýSoubor.java
xdg-open **/HlubokoVBalíčcíchPohřbenýSoubor.java
Není to lepší? (Nějaký novější bash to už prý umí také)

25.6.2010 11:20 BostX
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Sorry ale find s jeho 50 000 parametrami je strasny bordel. Normaly clovek nie je schopny mentalne spracovat (= pochopit a oddebugova) prikaz s viac ako 4 az 5 parametrami.

Ovela lepsie je napisat si kratsi find s par parametrami, jeho vysledok prechadzat v cykle a vypisat si medzivysledky!

A aj tak tomu polka kolegov poriadne neporozumie.
David Watzke avatar 25.6.2010 11:40 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Nesouhlasím. Jsem možná nenormální, ale tohle stejně pochopím:
find -depth -mindepth 1 -maxdepth 5 \( -type f -o -type l \) \( -name '*.docx' -o -iname '*.doc' \) -delete
:-)
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
25.6.2010 14:41 lib | skóre: 9
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
+1
26.6.2010 11:30 me
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Ano, mate pravdu, find je komplikovanejsi prikaz. Normalnimu smrtelnikovi se staci nasprtak dva nebo tri nejbeznejsi paramtry a s temi vystaci hodne dlouho. Expert rosirene moznosti find taky oceni...
26.6.2010 20:47 Ash | skóre: 53
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Ovela lepsie je napisat si kratsi find s par parametrami, jeho vysledok prechadzat v cykle a vypisat si medzivysledky!

Omg, no když myslíte...
Oveľa lepšie je:
 - napísať si kratší find
   * s pár parametrami
   * jeho výsledok: 
        1) prochádzať v cykle
        2) vypísať si medzivýsledky!
27.6.2010 17:20 chsajarsa | skóre: 16 | blog: V_hlouby_destneho_pralesa | Lovosice(Praha)
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Lepsi je mit obe moznosti a find jde pouzivat i jednoduse. To je podle me jedna ze zakladnich vyhod unixu, ze k cili je mnoho cest. Ja napr. find nepouzivam pro jednoduche hledani. Na to je locate a whereis kdyz to neni v db,tak ls -lR + nejaky grep. Na slozitejsi veci ten find.
~ QED ~
28.6.2010 05:38 Ash | skóre: 53
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Více možností je určitě dobře. Já třeba asi nepochopím v čem je
ls -lR | grep foo
jednodušší než
find . -name '*foo*'
ale chápu že to může chápat někdo jiný :)
28.6.2010 08:59 chsajarsa | skóre: 16 | blog: V_hlouby_destneho_pralesa | Lovosice(Praha)
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Vubec v nicem. je to jen o stilu prace. Jsme hodne zvyklej pracovat s pipou a proto treba pouzivam cat neco | grep neco_dalsiho. Je to i castecne diky tomu,ze dost prebiham mezi ruznymi unixy a proste nez,abych premyslel jak se to kde chova tak to napisu takhle. Nic vic v tom neni.

Skripty jsou samozdrejme neco jineho. Tam se snazim byt co nejuspornejsi k procesorovemu casu :-)
~ QED ~
25.6.2010 12:12 jurasek
Rozbalit Rozbalit vše find na FS s ACL
Odpovědět | Sbalit | Link | Blokovat | Admin
Nevite nekdo jestli jde pouzit find na vyhledavani majitele nebo skupiny souboru na FS s aktivnimi ACL a pravy nastavovanymi pres setfacl ?

jura
David Watzke avatar 25.6.2010 12:20 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: find na FS s ACL
Nevím zda to jde přímo, ale rozhodně lze na každej nalezenej soubor spustit nějakej skript, kterej to zjistí (pomocí přepínače -exec nebo jinak).
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
25.6.2010 17:52 VSi | skóre: 28
Rozbalit Rozbalit vše Re: find na FS s ACL
Nevím přesně jak je dotaz myšlen, ale "POSIX" acl, která se nastavují přes setfacl, nijak nemění sémantiku majitel-skupina, která se používá normálně. Prostě pořád má ten soubor/adresář vlastníka+skupinu, dále má klasická UNIX práva, a k tomu navíc jsou definovaná práva pro další uživatele a skupiny. find tedy bude pracovat s tím klasickým vlastníkem a skupinou, ale nebude umět třeba vypsat jen soubory, ke kterým má v ACL nastavená práva určitá skupina.
27.6.2010 10:14 jurasek
Rozbalit Rozbalit vše Re: find na FS s ACL
OK. To chapu, ze bude stale umet pracovat se zakladnimi pravy ugo. Existuje nejaky nastroj, ktery by mi umel vyhledat v souborech, ktere maji nastaveno vice skupin pres ACL napriklad tu druhou a dalsi skupinu ?

jura
25.6.2010 13:00 user
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Ahoj,

jaky je rodil mezi

find -iname *.pdf a find -iname '*.pdf'

Na dotaz s temi apostrofy mi to vrati vice vysledku, ale nechapu proc.

Muzete mi to nekdo prosim vysvetlit ?
David Watzke avatar 25.6.2010 13:12 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
No tak bez apostrofů to expanduje shell, takže se ten výraz nahradí vším s příponou .pdf v pracovním adresáři. Mezi apostrofy to hledá rekurzivně vše s příponou .pdf.
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
frEon avatar 25.6.2010 17:49 frEon | skóre: 40 | Praha
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
nebo lze hodit pred * znak \, tedy -iname \*.pdf
Talking about music is like dancing to architecture.
default avatar 25.6.2010 17:54 default | skóre: 22 | Madrid
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
Tady stojí za zmínku, že zde popisovaný find je opravdu čistě GNU/Linuxová záležitost. Na ostatních UNIXových či UNIX-like systémech se chová naprosto jinak a spoustu věcí neumí.

Pokud chcete psát cross-platform skripty, je lepší se findu vyhnout.

Nekamenujte mě. Píšu to jen proto, že seriál se jmenuje Unixové nástroje, nikoli Linuxové nástroje.

Jinak uznávám, že GNU verze je prostě nejlepší a preferuju ji. Bohužel né všude je k dispozici… :-(
David Watzke avatar 25.6.2010 17:56 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Single UNIX Specification popisuje totéž co já, až k sekci "GNU rozšíření". (Čímž se nesnažím vyvrátit tvoje tvrzení o přenositelnosti, jen o "linuxových nástrojích".)
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
default avatar 25.6.2010 18:03 default | skóre: 22 | Madrid
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
V pohodě. Já jen na tohle upozorňuji, protože u žádnýho jinýho UNIXovýho nástroje jsem se nesetkal s tak šílenou nekompatibilitou.

Zbytek byly jen drobnosti typu že nelze překódovat iconvem soubor z jednoho kódování do toho samého a tak podobně. Upravit skript tak, aby mu tyto drobnosti nevadily, je v pohodě. V případě findu je to kolikrát major redesign (a následný major rewrite). :-)

Navíc né každý plně implementuje UNIX Specification. Každý druhý má své Exceptions: because of backward compatibility, you know, heh. :-D
26.6.2010 11:35 me
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
A kdyz se vyhnete "findu", cim jej ve skriptech nahradite? Vetsina UNIX prikazu nepodporuje rekurzivni zpracovani adresaru (GNU utility toto uz take umi, ale ty taky pouzivat nemuzeme, nejsou prenosne... ;-). Myslim si, ze findu se nelze uplne vyhnout, ale je treba omezit parametry jen na ty zakladni.
1.7.2010 15:31 bender
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
Odpovědět | Sbalit | Link | Blokovat | Admin
a bude někdy v rámci tohoto seriálů představen i super nástroj sl?
1.7.2010 15:54 Ash | skóre: 53
Rozbalit Rozbalit vše Re: Unixové nástroje – 14 (find)
:) Možná by stačil odkaz sl.

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.