A fájlnevek behelyettesítése a shell-ben

Láttunk már néhány olyan karaktert, amelynek valamilyen speciális jelentése van a shell számára; a pontosvessző a parancsokat határolja, a kerek zárójelek a parancsok csoportosításakor használatosak, a '&' jel a háttérben futtatást jelzi, stb. Ezeket a karaktereket szokták metakaraktereknek nevezni, mivel betű szerinti értelmükön túlmutató jelentésük is van. Ebben a pontban néhány újabb metakarakterrel ismerkedünk meg, amelyek a shell egy igen fontos mechanizmusában, a fájlnevek behelyettesítésében kapnak szerepet.

Ha a shell a parancssor valamelyik szavában a kérdőjel (?) vagy csillag (*) karakterek valamelyikét találja, ezeket helyettesítő karakternek értelmezi, s az őket tartalmazó szót megpróbálja az aktuális katalógusban lévő fájlnevekre illeszteni. A '?' karakter bármelyik karakterre illeszkedhet, a '*' karakter pedig tetszőleges számú és tetszőleges karakterre illeszkedik. Ha a shell talált az adott argumentumra illeszkedő fájlnevet, akkor behelyettesíti azt az argumentum helyére. Nézzük meg mindezt néhány példán! Tegyük fel, hogy katalógusunk az alábbi fájlokat tartalmazza:

 

$ ls

FULL-INDEX file newdir newfilee2 sendmail.cf text

akarmi file1 newfile semmi temp

$

Most próbáljunk meg helyettesítő metakaraktereket tartalmazó argumentumokat megadni az ls parancsnak, s nézzük meg, ezeket milyen fájlnevekre tudja ráilleszteni a shell. Első példánkban a shell az 'f' betűvel kezdődő, utána egy tetszőleges karaktert tartalmazó, majd az 'le' karakterekre végződő nevű fájlt keres a kurrens könyvtárban; egy ilyet talált, a file nevűt:

 

$ ls f?le

file

Hasonlóképpen a második minta a 'file' betűkkel kezdődő, és még egy tetszőleges karaktert tartalmazó nevet keres - ez a file1 állományra illeszkedett.

 

$ ls file?

file1

A következő példa a 'file' karakterekkel kezdődő, s bármivel folytatódó nevekre illeszkedik: ebbe belefér az az eset is, ha nulla darab karaktert vesz a shell, ezért illeszkedik a file állománynévre is!

 

$ ls file*

file file1

Az alábbi példa az akármivel kezdődő, a 'file' szócskával folytatódó, s akármivel befejeződő nevekre illeszkedik:

 

$ ls *file*

file file1 newfile newfilee2

Ez a példa az akármivel kezdődő, a 'file' karakterek után egy tetszőleges karaktert tartalmazó nevekre illeszkedik:

 

$ ls *file?

file1

Utolsó példánkban egy olyan mintát adtunk meg, ami semmilyen fájlnévre nem illeszkedik a kurrens katalógusban - ilyenkor a shell változatlanul hagyja az argumentumot, azaz az ls parancs az x* nevet fogja megkapni, s joggal panaszkodik, hogy ilyen fájl nem létezik:

 

$ ls x*

x* not found

$

A '?' és a '*' karaktereket dzsóker-karaktereknek is nevezik, a fájlnév behelyettesítésben betöltött szerepükre utalva.

Még egy dzsóker-mechanizmus is rendelkezésre áll, ez a karakterosztály megadásának lehetősége. A szögletes zárójelek '[...]' között megadott karakterek egy karakterosztályt definiálnak: az ezt tartalmazó minta illeszkedni fog bármelyik olyan karakterre a fájlnevekben, amelyik a karakterosztályban szereplő bármelyik karakterrel azonos. Egy példa: az a[xyz] minta illeszkedni fog az ax, ay és az nevekre. Lehetőség van továbbá arra is, hogy az ASCII kódkészlet szerint egymás után következő sok karaktert a mínuszjel felhasználásával, tól-ig formában adjuk meg. Az src[0-9] minta illeszkedni fog az src0, src1, ... src9 fájlokra. Vigyázat, egy karakterosztály megadása mindig egy karakterre illeszkedik, ha például kétjegyű számokkal végződő mintát szeretnénk megadni, valahogy így kéne: src[0-9][0-9].

A karakterosztályoknál karakterek ellentettjét is kereshetjük, a '^', illetve újabb shellekben a '!' karakterek megadásával. Így tehát a '[!a-z]' bármely olyan karakterre illeszkedik, ami nem kisbetű. (Ha magát a '^' vagy a '!' karaktert szeretnénk tagadni, az első helyen kell szerepeltetni a karakterosztályon belül, pl. '[!!a-z]' minden olyan karakterre illeszkedik, ami nem felkiáltójel, vagy kisbetű.)

Van még egy apróság, amire nem árt, ha vigyázunk a mintamegadásokkor: akárcsak az ls parancs, a shell is eltérően kezeli a rejtett fájlokat, és alapértelmezés szerint a '.', illetve a '*' jel hatálya nem terjed ki a névkezdő pont karakterre. Ennek az a következménye, hogy a '*' minta például minden létező fájlnévre illeszkedni fog, kivéve a rejtetteket. Ha azokat is látni akarjuk, explicit módon meg kell adni a szókezdő pont karaktert a mintában, például ls .*. (ennek viszont az a következménye lesz, hogy a kurrens és a szülő katalógusra való hivatkozás ('.' és '..') is illeszkedik a mintára, tehát azok tartalmát is kilistázza az ls. Megoldás? ls .[!.]*

Végül ismét csak nyomatékosan emlékeztetünk arra, hogy a fájlnév behelyettesítést mindig a shell végzi el, s a meghívott program már a behelyettesített fájlneveket kapja meg: egyik előző példánknál maradva, amikor mi az ls file* parancsot adtuk ki, a shell két illeszkedő állománynevet talált (file és file1), s ezeket behelyettesítette az eredeti parancsba. Amikor tehát a shell ténylegesen meghívja majd az ls parancsot, úgy fogja látni, mintha mi az ls file file1 parancsot adtuk volna ki, nem fog tudni arról, hogy hogyan nézett ki a parancssor eredeti mivoltában.

A DOS és UNIX metakarakterek

A DOS-t ismerők figyelmébe ajánljuk a DOS és a UNIX metakarakter értelmezése közti fontos különbséget: míg a UNIX konzekvensen csinálja a mintaillesztést, addig a DOS ezt - finoman szólva - eléggé elnagyoltan utánozta le. A DOS alatt például a mintában szereplő karakterek az első '*' karakter után figyelmen kívül maradnak (mindez külön-külön igaz az állománynévre, illetve az utótagra). A UNIX shell azonban végignézi a mintát, s csak olyan állományneveket helyettesít be, amelyek a teljes mintának megfelelnek. Tehát ha van egy abc és egy ade nevű állományom, a DOS az a*c mintára mindkettőt megtalálja (rosszul!), míg a UNIX csak az abc nevűt.

 

Tartalomjegyzék