9. Keresés a fájlrendszerben¶
A fájlrendszerben történő keresést az egyes operációs rendszerek fontos kérdésként kezelik. A Unixok általában több parancsot is kínálnak erre a feladatra, amelyek működési módja és szolgáltatási köre is más és más.
9.1. A find¶
A find parancs fájlok, könyvtárak stb. keresésére szolgál. Rendkívül gazdagon paraméterezhető, és támogatja a megtalált fájlok feldolgozását is. A működését példákon keresztül mutatom meg.
A leggyakrabban úgy használom, hogy egy könyvtárból kiindulva keresek fájlt vagy fájlokat, amelyeknek ismerem a nevét vagy annak jellemző részletét. Ezeket a parancsban paraméterként kell megadni. A példában a etc
könyvtárban és annak alkönyvtáraiban keresem a passwd
fájlt. Először a kiinduló könyvtár nevét adom meg, majd a -name kapcsoló után a keresendő fájl vagy könyvtár nevét. (A példában a találatok mellett több sornyi hibaüzenet is megjelenik, mert egyszerű felhasználóként nincs olvasási jogosultságom néhány könyvtárra.)
feri@columbo:~/demo$ find /etc -name passwd
find: „/etc/vmware-tools/GuestProxyData/trusted”: Engedély megtagadva
/etc/pam.d/passwd
find: „/etc/chatscripts”: Engedély megtagadva
/etc/cron.daily/passwd
find: „/etc/ssl/private”: Engedély megtagadva
find: „/etc/ppp/peers”: Engedély megtagadva
find: „/etc/apt”: Engedély megtagadva
find: „/etc/polkit-1/localauthority”: Engedély megtagadva
/etc/passwd
Megismétlem a parancsot úgy, hogy a hibaüzeneteket a /dev/null fájlba irányítom. Most már jobban látható, hogy három passwd
nevű fájl van a /etc
könyvtárból indulva:
feri@columbo:~/demo$ find /etc -name passwd 2>/dev/null
/etc/pam.d/passwd
/etc/cron.daily/passwd
/etc/passwd
A find esetében használhatod a helyettesítő karaktereket is a keresendő fájl vagy könyvtár nevének megadásakor:
feri@columbo:~/demo$ find /etc -name 'a?d*.conf' 2>/dev/null
/etc/adduser.conf
/etc/init/atd.conf
9.1.1. Típus¶
Lehetőséged van arra is, hogy csak fájlt, könyvtárt, linket vagy más típusú elemet keress, ehhez a -type paraméter után kell megadnod a keresett bejegyzés típusát. A példában a passwd
nevű fájlokat szeretném megkeresni a /etc
könyvtárban, ezért a -type f kapcsolót használom.
feri@columbo:~/demo$ find /etc -name passwd -type f 2>/dev/null
/etc/pam.d/passwd
/etc/cron.daily/passwd
/etc/passwd
A -type lehetséges értékei:
- f:
Fájl
- d:
Könyvtár
- l:
Softlink
- c:
Karakteres eszközfájl
- b:
Blokkos eszközfájl
- s:
Socket
- p:
Named pipe
9.1.2. Mélység¶
A fenti példákban is láthattad, hogy a find a keresést nem csak a megadott könyvtárban végzi, hanem az abból nyíló összesben is. Ha ezen változtatni akarsz, a -mindepth és a -maxdepth paramétereket használhatod. Mindkettő után meg kell adnod, hogy milyen mélységig akarsz keresni. A -maxdepth 1 megadásával a megadott könyvtár alatt egy szinttel még megtörténik a keresés, de az alatt már nem. A -mindepth hasonlóan működik, de ezzel a minimális keresési mélységet állíthatod be. Az alábbi példában csak az /etc
könyvtárban és egy szinttel alatt keresem a passwd
nevű fájlokat.
feri@columbo:~/demo$ find /etc -maxdepth 1 -type f -name passwd
/etc/passwd
Fontos, hogy ha használod ezeket a paramétereket, akkor elsőként add meg őket úgy, ahogyan a fenti példában látod.
9.1.3. Dátumok¶
A find néhány nagyon hasznos paramétere a fájlok különféle időpontjainak kezelésére való. Leggyakrabban a -ctime-ot szoktam használni arra, hogy egy könyvtárban egy megadott számú napnál régebben keletkezett fájlokat keresek pl. azért, mert törölni szeretném őket. Lássunk erre is egy példát, keressünk 1200 napos vagy annál öregebb fájlokat:
feri@columbo:~/demo$ find /etc -type f -ctime +1200 -name 'pa*' 2>/dev/null
/etc/pam.d/passwd
/etc/init/passwd.conf
/etc/cron.daily/passwd
/etc/pam.conf
/etc/exim4/passwd.client
A -ctime paramétere tehát a napok száma, melyet előjellel vagy anélkül írhatsz le. A +3
azt jelenti, hogy a mai dátumnál három nappal vagy korábban keletkezett fájlokat keresed. A -5
pedig azt, hogy a fájl dátuma a mai napétól legfeljebb 5 nappal lehet kisebb. Ha nem használsz előjelet, akkor a pontos napszámot adod meg.
Az -atime ugyanígy működik, de a fájl utolsó olvasására, az -mtime az utolsó módosítás dátumára vonatkozik.
Ha nem napokkal szeretnél dolgozni, másik három paramétert kell használnod, a nevük: -amin, -cmin és -mmin. Ezek paramétereként perceket kell megadnod. Az alábbi példában a 30 percnél nem régebben módosított fájlokat keresem. Először nem találok ilyet, de miután hozzáírtam egy sort az egyikhez, annak módosítási dátuma az aktuális idő lett, így a parancs ismételt kiadása után már látható ennek eredménye.
feri@columbo:~/demo$ find . -mmin 30
feri@columbo:~/demo$ echo alma >>teszt.txt
feri@columbo:~/demo$ find . -mmin -30
./teszt.txt
A dátumokkal kapcsolatos keresésekben ún. referencia fájlt is használhatsz. Ebben az esetben nem konkrét napot, vagy percet kell megadnod, hanem egy fájlt, amelyeknél fiatalabb fájlokat keresel. Az alábbi példában a helloWorld.txt
fájlnál később módosított fájlokat keresem meg:
feri@columbo:~/demo$ find . -newer helloWorld.txt
./teszt.txt
9.1.4. Méret¶
A keresés szempontja lehet a fájl mérete is, ehhez a -size paramétert kell használnod. Hasonlóan a fájl dátumait kezelő paraméterekhez, ebben az esetben is megadhatsz pontos értéket, de használhatsz előjeles értékeket is. A mérete megadásakor prefixek is megadhatók. A +2k
a 2 kbyte-nál nagyobb fájlokat, a -2k
a 2 kbyte-nál kisebbeket, a 2k
a pontosan 2 kbyte-osakat jelenti. Értelemszerűen, a b
jelentése byte, az M
megabyte-ot, a G
gigabyte-ot jelent.
A példában az 1 kbyte-nál kisebb fájlokat keresem:
feri@columbo:~$ find /etc -type f -size -1k 2>/dev/null
/etc/init.d/.legacy-bootordering
/etc/resolvconf/resolv.conf.d/base
/etc/security/opasswd
/etc/update-notifier/hooks_seen
/etc/newt/palette.original
/etc/.pwd.lock
/etc/sensors.d/.placeholder
9.1.5. Jogosultság¶
A fájlok, könyvtárak jogosultságaira is lehet keresni, ere a -perm kapcsoló szolgál. A következő példában a /bin
könyvtár setuid-es programjait keresem, ezek jogosultsága 0755.
feri@columbo:~$ find /bin -perm 4755
/bin/su
/bin/mount
/bin/ping
/bin/umount
/bin/fusermount
/bin/ping6
9.1.6. Tulajdonos, csoport¶
Ha adott csoport vagy tulajdonos a keresési szempont, a -group vagy a -user paraméter jelenti a megoldást.
A root csoport által birtokolt fájlok keresése a /tmp
könyvtárban:
feri@columbo:~$ find /tmp -group root 2>/dev/null
/tmp
/tmp/mc-root
/tmp/vgauthsvclog.txt.0
/tmp/vmware-root
A feri felhasználó tulajdonában álló fájlok keresése a /tmp
könyvtárban:
feri@columbo:~$ find /tmp -user feri 2>/dev/null
/tmp/mc-feri
9.1.7. Feldolgozás¶
A keresés során megtalált fájlok fel is dolgozhatók, erre a -exec paraméter szolgál. A használata gyakorlatilag egy vagy több parancs végrehajtását jelenti minden egyes megtalált fájl esetén. A parancs leírásakor az éppen megtalált fájlra a {}
karakterpárral hivatkozhatsz, a parancsot lezárni a \;
karakterekkel lehet.
Lássunk egy példát! Keressük meg a 100 napnál öregebb fájlokat a /tmp
könyvtárban, és minden egyes megtalált fájl esetén adjuk ki az ls -l <filenev> parancsot! (Néhány példában most a sudo használatával dolgozom, hogy ne okozzon problémát a jogosultság hiánya.)
feri@columbo:~$ sudo find /tmp -mtime -100 -type f -exec ls -l {} \;
-rw-rw-r-- 1 Y2X6SX Y2X6SX 218008 júl 30 03:10 /tmp/find-ahavasi.txt
-rw-r--r-- 1 root root 8956 júl 18 12:21 /tmp/vgauthsvclog.txt.0
-rw-r----- 1 root root 4164 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1525.log
-rw-r----- 1 root root 4873 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1448.log
-rw-r----- 1 root root 4873 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1462.log
-rw-r----- 1 root root 4517 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1494.log
-rw-r----- 1 root root 4454 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1438.log
-rw-r----- 1 root root 4524 júl 18 12:21 /tmp/vmware-root/vmware-apploader-1431.log
A következő példában ezeket a fájlokat áthelyezem a /tmp/backup
könyvtárba úgy, hogy a -exec paramétereként a mv {} /tmp/backup ; parancs végrehajtását határozom meg:
feri@columbo:~$ sudo find /tmp -mtime -100 -type f -exec mv {} /tmp/backup \;
feri@columbo:~$ ls -l /tmp/backup/
-rw-rw-r-- 1 Y2X6SX Y2X6SX 218008 júl 30 03:10 find-ahavasi.txt
-rw-r--r-- 1 root root 8956 júl 18 12:21 vgauthsvclog.txt.0
-rw-r----- 1 root root 4524 júl 18 12:21 vmware-apploader-1431.log
-rw-r----- 1 root root 4454 júl 18 12:21 vmware-apploader-1438.log
-rw-r----- 1 root root 4873 júl 18 12:21 vmware-apploader-1448.log
-rw-r----- 1 root root 4873 júl 18 12:21 vmware-apploader-1462.log
-rw-r----- 1 root root 4517 júl 18 12:21 vmware-apploader-1494.log
-rw-r----- 1 root root 4164 júl 18 12:21 vmware-apploader-1525.log
A megtalált fájlok törlése olyan gyakori feladat, hogy erre a find esetében egy önálló kapcsolót vezettek be, ennek -delete a neve. Használata egyszerűbb, mint az -exec paraméterezése.
feri@columbo:~$ sudo find /tmp -mtime -100 -type f -delete
Általános probléma, hogy a felhasználók nem törlik a felesleges leveleiket, amikor pedig betelik a postafiókjuk, azt kérik, hogy egy adott dátum előtti összes leveleüket törölje a rendszergazda. Ennek megoldásakor is jól jön a find parancs: először készíts egy fájlt úgy, hogy annak készítési dátuma az általad elvárt legyen, majd használd a -mtime paramétert (jelen példánkban tagadással). Ha pl. szeretnél egy könyvtárból (és annak könyvtáraiból) minden fájlt törölni, ami korábban módosult 2018. január 1-jénél, akkor így így tudod megoldani:
feri@columbo:~$ touch -t 201801010000 /tmp/2018-Jan-01-0000
feri@columbo:~$ find . -type f ! -newer /tmp/2018-Jan-01-0000 -delete
Mielőtt élesben futtatod a find parancsot, érdemes előzetesen megnézni az eredményt a -delete használata nélkül, így megtekintheted, mely fájlokat is fogod majd törölni. Ez sokkal egyszerűbb, mint a hibás parancs után a mentésből helyreállítani azokat a fájlokat, amiket mégsem kellett volna törölnöd.
9.1.8. Az xargs és a find¶
Ha a find parancsot az xargs-szal szeretnéd használni, problémát okozhatnak azok a fájlok, amelyeknek a nevében szóköz van. Ezeket ugyanis az xargs több fájlnévkét fogja értelmezni, hiszen a paraméterek elválasztó karaktere a szóköz. A példához létrehoztam egy olyan fájlt, amelynek a nevében szóköz van:
feri@columbo:~/demo$ touch 'Hello World.txt'
feri@columbo:~/demo$ ls -l *.txt
-rwxr-xr-x 1 feri feri 0 júl 28 22:28 helloWorld.txt
-rw-rw-r-- 1 feri feri 0 júl 30 16:49 Hello World.txt
-rw-rw-r-- 1 feri feri 46 júl 29 23:27 teszt.txt
Keressük meg a .txt kiterjesztésű fájlokat, és jelenítsük meg részletes adataikat az xargs-szal úgy, hogy az ls -l paramétereként adjuk meg őket!
feri@columbo:~/demo$ find . -name '*.txt' | xargs ls -l
ls: ./Hello nem érhető el: Nincs ilyen fájl vagy könyvtár
ls: World.txt nem érhető el: Nincs ilyen fájl vagy könyvtár
-rwxr-xr-x 1 feri feri 0 júl 28 22:28 ./helloWorld.txt
-rw-rw-r-- 1 feri feri 46 júl 29 23:27 ./teszt.txt
Látható, hogy a Hello World.txt
zavart okoz, az xargs két paraméterként kezeli. A megoldást az jelenti, hogy mind a find, mind az xargs számára jelezzük, hogy a fájlok neveit a régi jó C-s formában, a 0-s kódú karakterrel zárva kezeljük. Ebben az esetben a fájlnévben levő szóköz már nem számít az xargs-nak, mert a záró 0 kódú karaktert fogja használni. A fenti példában ezért a find számára egy -print0
paramétert adok, ezzel 0-val terminált stringekként képzi a fájlneveket, az xargs-nak pedig egy -0
paramétert, amivel az 0-val zárt stringként várja az egyes paramétereket. Példánk ennek megfelelően így alakul:
feri@columbo:~/demo$ find . -name '*.txt' -print0 | xargs -0 ls -l
-rwxr-xr-x 1 feri feri 0 júl 28 22:28 ./helloWorld.txt
-rw-rw-r-- 1 feri feri 0 júl 30 16:49 ./Hello World.txt
-rw-rw-r-- 1 feri feri 46 júl 29 23:27 ./teszt.txt
Veszélyforrás!
Az xargs használata esetén érdemes mindig ezt a módszert használni, mert ha pl. fájlok törlését akarod így elvégezni, könnyen érhet kellemetlen meglepetés. Ilyen lehet, ha a törlendő fájlok nevében szóköz van, netán a töredékek nevével van olyan fájl is, amit eredetileg nem szerettél volna törölni. (A fenti példában, ha lenne ott
World.txt
, az a hibás parancsod áldozatául esne.)
9.2. whereis¶
A whereis futtaható programok, forrás fájlok és/vagy kézikönyv fájlok keresésére szolgál úgy, hogy a keresést csak azok ajánlás szerinti tárolási helyein teszi meg. Ezek a könyvtárak sajnos Unix variánsonként eltérőek lehetnek. A legtöbb rendszerben a futtatható fájlok a /bin
, az /usr/bin
, az /sbin
, az /usr/bin
az /usr/local/bin
és az /usr/local/sbin
könyvtárakban vannak. A man parancs működéséhez szükséges fájloknak is az adott rendszer erre a célra szolgáló könyvtáraiban, kell lenniük ahhoz, hogy mind a man, mind a locate működjön.
Lássunk egy példát: kapcsolók nélkül a parancs az említett fájltípusok mindegyikére keres:
feri@columbo:~/demo$ whereis chmod
chmod: /bin/chmod /usr/share/man/man2/chmod.2.gz /usr/share/man/man1/chmod.1.gz
A találatok szűkíthetők, megadhatod, hogy pontosan melyik típus érdekel. A -b kapcsoló csak a futtatható programokat (binárisokat), a -m a kézikönyv oldalakat, a -s a forrás fájlokat keresi. Az alábbi példában csak a chmod
nevű programfájlt keresem:
feri@columbo:~/demo$ whereis -b chmod
chmod: /bin/chmod
9.3. locate¶
A locate parancs a működése során nem a fájlrendszerben keres, hanem egy előre elkészített adatbázisban, amely tartalmazza az egyes fájlok helyét és nevét. Az adatbázist az updatedb paranccsal lehet frissíteni. Lássunk egy példát, a chmod szóra keressünk rá a locate segítségével!
feri@columbo:~$ locate chmod
/bin/chmod
/usr/lib/mc/fish/chmod
/usr/share/man/man1/chmod.1.gz
/usr/share/man/man2/chmod.2.gz
/usr/share/man/man2/fchmod.2.gz
/usr/share/man/man2/fchmodat.2.gz
A parancs nem csak a chmod parancsot keresi meg, hanem minden olyan fájlt, aminek a nevében szerepel a chmod szó.
Azt, hogy a működés egy adatbázison alapul, az alábbi példában látható. Először létrhozok egy helloWorld
fájlt, majd megpróbálom megkeresni a locate paranccsal. Látható, hogy nem kapok találatot:
feri@columbo:~/demo$ touch helloWorld
feri@columbo:~/demo$ locate helloWorld
feri@columbo:~/demo$
Most lefuttatom az adatbázis frissítésére szolgáló parancsot, az updatedb-t. Mivel ehhez felhasználóként nincs jogom, ezért rendszergazdaként teszem ezt meg. (A sudo parancsról a A sudo c. fejezetben lesz majd szó.)
feri@columbo:~/demo$ sudo updatedb
[sudo] password for feri:
Mivel az updatedb parancs frissíti az adatbázisát, az ez után végrehajtott locate parancs már megtalálta a helloWorld
fájlt.
feri@columbo:~/demo$ locate helloWorld
/home/feri/demo/helloWorld
Tipp
Bizonyára felmerült benned a kérdés, hogy az updatedb parancsot mikor és kinek kell futtatnia? Nem tűnik jó megoldásnak, hogy azt az egyszerű felhasználó tegye. A megoldást egy ütemezett feladat jelenti. A működéséről a A cron fejezetben volt szó.
9.4. which¶
A which parancs futtatható fájlokat keres a $PATH
környezeti változóban meghatározott könyvtárakban keres. Mielőtt megnézzük a működését, nézzük meg a $PATH
tartalmát!
feri@columbo:~/demo$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Keressünk rá a chmod parancsra! Ez a /bin
könyvtárban van, ami a $PATH
változó könyvtáraiban meg is található:
feri@columbo:~/demo$ which chmod
/bin/chmod
Ha az előző példában látott helloWorld
fájlra keresnék rá ezzel, nem kapnék találatot, hiszen az aktuális könyvtár nem szerepel a $PATH
változóban. Mivel csak futtatható fájlok jöhetnek szóba, először beállítom ezt:
feri@columbo:~/demo$ chmod 755 helloWorld
Majd elvégezzük a keresést, és látjuk, hogy nincs találat:
feri@columbo:~/demo$ which helloWorld
feri@columbo:~/demo$
Csak a példa kedvéért most elkövetem azt a disznóságot, hogy az aktuális könyvtárat is ráteszem a keresési útvonalra. Ahogyan a A PATH környezeti változó c. részben már láttad, ezt egy éles rendszerben veszélyes lenne beállítani.
feri@columbo:~/demo$ PATH=$PATH":."
feri@columbo:~/demo$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:.
feri@columbo:~/demo$ which helloWorld
./helloWorld
Tipp
A fentiek alapján az egyes parancsok célszerű felhasználási területe:
- find:
Ha a keresett fájl bárhol lehet a fájlrendszerben, vagy speciális feltételeket akarsz megadni a kereséshez.
- locate:
Ha programfájlt, kézikönyv oldalt vagy forrás fájlt keresel.
- which, whereis:
Ha kifejezetten programfájlt keresel, és fontos a gyors válaszidő.
9.5. Ellenőrző kérdések¶
Milyen keresési parancsokat ismer?
Milyen különbségek vannak az egyes keresési eljárások közt?
Milyen keresési lehetőségeket biztosít a find?
Mi az xargs és miért van rá szükség?
Hogyan lehet a keresés eredményével további műveleteket végezni?
9.6. Feladatok¶
Keresd meg az
/etc
könyvtár .conf kiterjesztésű fájljait!Keresd meg a
/etc
könyvtár 30 napnál nem régebben módosított fájljait!Keresd meg a
/etc
könyvtár softlinkjeit!Keresd meg a
/etc
könyvtár 100Kbyte-nál nagyobb méretű fájljait!Keresd meg a
/etc
könyvtárban azokat a fájlokat, amelyek tulajdonosa nem a root user!Töröld a
/tmp
könyvtárban az összes 10 KByte-nál nagyobb txt kiterjesztésű fájlokat, amelyek tulajdonosa a bela user!A whereis használatával keresd meg az ls parancs helyét!
Végezd el ugyanezt a locate paranccsal is!