Hlavní navigace

Hrátky z řádky: find to najde

Petr Macek 14. 4. 2008

Opět se setkáváme u pravidelné pondělní dávky tipů a triků z černé řádky. Dnes se vracíme k hledání. Celý díl bude věnován příkazu find. Ten je velmi mocný, jak dále uvidíte, umožní nám víc než jen hledání. Find prochází adresářovou strukturu a dokáže nad soubory provádět různé užitečné akce.

Find má mnoho parametrů. Zpočátku se vám bude zdát, že zápis moc nedává smysl a že si ho nikdy nezapamatujete. Naštěstí proto tu máme manuálovou stránku.

Struktura příkazu vypadá následovně:
find cesta výraz

Cesta je jasná – od tohoto adresáře níže se bude hledat. U některých verzí find můžeme cestu vynechat a použije se aktuální. U výrazu je to složitější. Sem spadají volby, které obecně ovlivňují hledání, pomocí nich například můžeme říct jen od/do které úrovně (mindepth, maxdepth) hledat, zda procházet symbolické odkazy (follow), … Dále zde máme testy – ty už se týkají hledaných objektů. Z často používaných je to např. typ (adresář, soubor, link, …), vlastník (user, group). Další důležitou možností jsou tzv. akce (exec, ok). Ty nám umožní spustit libovolný příkaz systému a jako parametr mu předat nalezený soubor. Nakonec tu máme operátory sloužící ke skládání výrazů. Jak každá část výrazu vrací hodnoty a jak probíhá vlastní zpracování je pěkně popsané v Linux – dokumentační projekt, kapitola 11. Tam odkazuji zvídavé čtenáře. My se zaměříme na praktické ukázky.

Úplný základ – hledá soubor s názvem soubor.txt v aktuálním adresáři a podadresářích:

$ find . -name soubor.txt

Vyhledá na disku všechny adresáře s názvem pokus (můžeme použít např. -type f pro soubory, -type l pro linky):

$ find / -type d -name pokus

Můžeme použít i zástupného znaku ? a *. Budeme hledat v domovském adresáři soubory s příponou txt, začínající postup_ (postup1.txt, postup_aaa.txt, …). Musíme zápis ošetřit, aby nebyl interpretován shellem:

$ find ~ -name postup_\*.txt

nebo

$ find ~ -name "postup_*.txt"

Pokud chceme vyhledat v aktuálním adresáři podadresáře a ty už dál rekurzivně neprocházet:

$ find . -type d -maxdepth 1

Je možné třeba i negovat podmínku, v domovském adresáři hledáme všechny soubory, co nemají příponu txt:

$ find ~ -type f \! -name \*.txt

Zajímavé je i hledání podle časů a velikostí souborů. To co napíšu teď se může trochu lišit v různých verzích findu, proto si pročtěte manuál.

Tento příklad najde v domovském adresáři vše co bylo modifikováno v posledních sedmi dnech:

$ find ~ -mtime -7d

Vše co bylo změněno před více než sedmi dny:

$ find ~ -mtime +7d

Přesně před sedmi dny:

$ find ~ -mtime 7d

Je možné použít písmenka s, m, h, d, w pro vteřiny, minuty, hodiny, dny a týdny. Stejně se dá hledat i podle velikostí, na to je parametr -size. -size +100k znamená větší než 100 kilobajtů, -100k menší než 100 kilobajtů a -size 100k je rovno. Pokud nezadáme k, bude výchozí hodnotou 512 bajtový blok. Pokud chceme podle bajtů, přidejte za číslo písmenko  b.

Vyhledá nám v aktuálním adresáři všechny soubory, které byly změněny dřív než soubor:

$ find . -newer soubor

Tento zápis už tak jednoduše nevypadá, přidáme navíc akci exec. Prázdné složené závorky ( {}) budou nahrazeny cestou k nalezenému souboru. Vykoná se příkaz ls -al s touto cestou. Zpětné lomítko před středníkem je důležité. Tím findu říkáme, kde končí příkaz, který chceme vykonávat. Ale středník je i znak, kterým se běžně oddělují příkazy. Při spuštění by se středník chápal jako oddělovač příkazů. Proto jej musíme ošetřit znakem \ nebo zapsat jako ";". Příklad najde v akt. adresáři a podadresářích všechny soubory a vypíše o nich detaily:

$ find . -type f -exec ls -al {} \;

Předchozí příklad nám ukazuje sílu findu. Toto nám smaže všechny soubory s příponou .old v současném adresáři a všech podadresářích:

$ find . -type f -name \*.old -exec rm {} \;

Pomocí findu můžete dělat i poměrně velké zásahy, takhle například změníte vlastnictví souborů jednoho uživatele na druhého:

$ find . -user user1 -exec chown user2 {} \;

Pokud si u -exec nejste jistí, že chcete třeba smazat vše co nám find našel, místo -exec použijte -ok. Před každým vykonáním se find zeptá, jestli akci opravdu provést.

Find má mnohem více možností, projděte si manuál, na různých webech věnujících se find najdete spoustu ukázek a praktických příkladů.

Někdy se můžeme setkat s využitím programu xargs. Ten čte v našem případě ze standardního vstupu jména souborů a vykonává nad nimi zadanou akci (v našem případě mazání):

$ find / -name "*.bak" | xargs /bin/rm -f

nebo

$ find / -name "*.bak" -print0 | xargs -0 /bin/rm -f

Vykonají stejnou funkci jako

$ find / -name "*.bak" -exec rm -f {} \;

V prvním příkladu chápe xargs jako oddělovače mezery a znak nového řádku, a to může být problém, např. když v názvu souboru bude mezera. V druhém případě oddělujeme jednotlivé soubory znakem NULL a mezera nás nemůže zaskočit. V případě bez xargs se rm spustí pro každý nalezený soubor, v tu chvíli find čeká na výsledek mazání. Když použijeme xargs, nalezené soubory určené k mazání se předávají xargs a ten po dosažení limitu (5000, ale můžete jej i změnit) spustí jedenkrát rm ( rm -f soubor1 soubor2 ...). Výsledek je potom o dost rychlejší. Ke xargs se ještě určitě vrátíme v dalších dílech.

Našli jste v článku chybu?

14. 4. 2008 18:00

smajl (neregistrovaný)
nebolo by lepsie na vymazanie suborov vyhovujucim hladaniu pouzit -delete ?

$ find / -name "*.bak" -exec rm -f {} \;

nahradit

$ find / -name "*.bak" -delete;





3. 11. 2010 19:03

BASH (neregistrovaný)

Ahoj, potreboval bych poradit ohledne vyhledavani v bashi. Pisu skript, ktery v zadanem adresari a jeho podadresarich identifikuje skripty a vypise jejich cestu + nazev skriptu. Vyhledani skriptu by se melo proves pres vyhledani nazvu skriptu na prvnim radku (napr.: "#!/bin/bash" nebo perl,awk,...)

napr.: pokud zadam adresar "script" vypise muj bashovsky skript toto:

/home/my/scrip­t/aaa.sh bash
/home/my/scrip­t/first/bbb.pl perl
/home/my/scrip­t/second/ccc.sh bash

Zatim sem se dostal k tomuh…



Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

DigiZone.cz: Recenze Prostřeno: cirkus postižených

Recenze Prostřeno: cirkus postižených

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Lupa.cz: EET v e-shopech? Zdražení a horší komfort

EET v e-shopech? Zdražení a horší komfort

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Podnikatel.cz: Hledáte investora? Neunáhlete se

Hledáte investora? Neunáhlete se

Vitalia.cz: Co pomáhá dítěti při zácpě?

Co pomáhá dítěti při zácpě?

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Měšec.cz: Přejete si číslo účtu na přání?

Přejete si číslo účtu na přání?

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Vitalia.cz: Co nabídne největší výživová konference FOOD21?

Co nabídne největší výživová konference FOOD21?

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí