Bevezetés
Követelmények
- A gyakorlatok látogatása ajánlott
- 2 db ZH (7. hét és 13. hét), a 14. héten pótlási lehetőséggel
- A jól teljesítők (elmélet + gyakorlat) megajánlott jegyben részesülhetnek
A dokumentum használata
Ez egy MarkDown formátumú dokumentum, ami jelen formájában egyben tartalmazza a gyakorlat tanagyagát. NEM tankönyv, csak VÁZLAT. Tartalma fejezetekre van osztva a témakörök szerint, a szövege könnyen kereshető.
Maga a fájl egy egyszerű (ASCII) szöveg, amit weben például GitHub, Androidon például a Markor nevű program tud formázottan megjeleníteni.
Miről fogunk tanulni?
- A Linux (/Unix) rendszerek parancssorának használatáról
- Az egyik leggyakoribb parancsértelmező (a Bash) használatáról
- Fontosabb parancsok
- „Egysoros programok”
- Shell scriptek (héjprogramok)
Miért van szükségünk erre a tudásra?
Azon kívül, hogy ZH-t írunk belőle...
- A Linuxot nagyon jól lehet szoftverfejlesztésre használni. Sok cégnél használják, de egyébként is az előnyünkre válhat.
- Linux (/Unix) szerverek.
- Beágyazott Linux (ipari robotok, Raspberry Pi
Honnan szerezzünk parancssort?
- Telepítsünk a saját gépünkre Linuxot
- Telepítsünk virtuális gépre Linuxot (ha kevésbé vagyunk bátrak)
- Használunk Live rendszert (USB pendrive-ról bootolható rendszert)
- Windows Subsystem for Linux (WSL), Windows 10-től elérhető
- Android: Termux
Az első lépések
Bejelentkezés
Helyi rendszerre: Felhasználónév és jelszó beírása
Távoli rendszerre: SSH kapcsolaton keresztül (pl. Putty programmal)
- IP cím
- Port (SSH alapértelmezett port: 22)
- felhasználónév
- jelszó
A laboron használt számítógépen a felhasználónév a Neptun kód (csupa kisbetűvel), a jelszó: 123
Parancsok beírása
Ahova a parancsokat be tudjuk írni: Prompt. Az éppen bevitt parancsban a szokásos módon tudjuk a nyíl billentyűkkel mozogni. Az enter billentyűvel adjuk ki a parancsot.
Hasznos billentyűkombinációk:
- Ctrl-C lelövi az aktuálisan futó programot, törli a bevitel alatt álló parancsot.
- Ctrl-L törli a képernyőt, kivéve az éppen szerkesztés alatt álló sort. Ez a legfelső sorba kerül.
- Ctrl-R keres az előzőleg bevitt parancsok között.
- Ctrl-D bevitel vége, vagy kilépés.
Jelszó megváltoztatása
password
Kéri a régi jelszót és az újat kétszer.
Mozgás a fájlrendszeren
cd KÖNYVTÁR
Relatív és abszolút útvonalak megadása lehetséges. A gyökérkönyvtár a / (perjel), az elválasztójel is / (perjel).
cd /
cd /home/abc123
cd ..
cd ../home
A cd parancs paraméterek nélkül kiadva a home könyvtárba lép.
cd -
Oda lép, ahol előzőleg álltunk.
Hol állok most?
Erre válaszol a
pwd
parancs. Az aktuális könyvtárt a prompt is jelzi.
Home könyvtár
Belépéskor minden felhasználó a saját home könyvtárában áll. Ennek útvonala általában
/home/felhasznalonev
Röviden:
~
Könyvtárak tartalmának listázása
Az ls paranccsal és kapcsolókkal történik.
ls
A nem rejtett bejegyzéseket betűrendben listázza, ha elég széles a terminál, akkor több oszlopban.
ls -a
A rejtett (.-tal kezdődő) bejegyzéseket is listázza.
ls -1
Egy oszlopban listáz.
ls -l
Hosszú formában listáz:
total 1688
-rw-r--r-- 1 root root 44 Aug 8 22:22 adjtime
drwxr-xr-x 1 root root 12 Dec 12 2019 alsa
drwxr-xr-x 1 root root 66 Aug 12 15:07 apparmor.d
-rw-r--r-- 1 root root 833 Aug 27 09:17 appstream.conf
-rw-r--r-- 1 root root 0 Dec 7 2021 arch-release
drwxr-xr-x 1 root root 138 Apr 29 12:24 audit
drwxr-xr-x 1 root root 142 Dec 21 2021 avahi
-rw-r--r-- 1 root root 505949 May 20 2020 avrdude.conf
-rw-r--r-- 1 root root 28 Jan 8 2022 bash.bash_logout
-rw-r--r-- 1 root root 618 Jan 8 2022 bash.bashrc
-rw-r--r-- 1 root root 2403 Aug 18 00:21 bind.keys
-rw-r--r-- 1 root root 535 Aug 8 21:27 bindresvport.blacklist
drwxr-xr-x 1 root root 0 Jan 11 2019 binfmt.d
drwxr-xr-x 1 root root 40 Feb 7 2021 bitlbee
Az egyes oszlopok jelentése:
- Típus és jogosultságok
- Linkszámláló
- Tulajdonos
- Csoport
- Méret
- Utolsó módosítás dátuma
- Név
ls -lh
A méretet átváltja (k, M, G, T stb).
ls -R
Rekurzívan listáz.
ls -t
Nem betűrendben, hanem a módosítás ideje szerint rendez.
ls -r
A rendezést megfordítja.
Az ls kapcsolói kombinálhatóak is, például:
ls -alR
Rejtett fájlokat is tartalmazó, hosszú formátumú rekurzív listát ad.
Fájl- és könyvtárműveletek
Új könyvtár létrehozása
Új könyvtárt az mkdir
paranccsal tudnk létrehozni. Megadható neki akár egy,
akár több könyvtár is.
mkdir ujkonyvtar
mkdir konyvtar1 konyvtar2 konyvtar3
Az mkdir
parancsnak megadhatunk egy útvonalat is, ha használjuk a -p
kapcsolót.
Ilyenkor a teljes útvonal mentén található összes könyvtárat létrehozza.
mkdir egyik/masik/harmadik
Létrejön az egyik
könyvtár, azon belül a masik
, azon belül pedig a masik
,
azon belül a harmadik
.
Másolás
Fájlok másolása a cp
paranccsal történik:
cp forrás cél
A forrás lehet egy, vagy több fájl, illetve könyvtár is. A cél egy esetet kivéve mindig könyvtár. (Ha a forrás egy fájl, akkor a cél is lehet fájl. Például le tudunk másolni egy fájlt egy új néven.)
A másolás során használhatunk dzsóker karaktereket is:
*
: Tetszőleges számú (akár 0 db is!) tetszőleges karaktert helyettesít.?
: Pontosan 1 db tetszőleges karaktert helyettesít.[K-V]
: K (kezdet) és V (vég) között bármilyen karaktert helyettesít.[K-V0-9abc]
: Ez a minta egy olyan karaktert helyettesít, ami vagy K és V között valami, vagy 0 és 9 között valami, vagy a, vagy b, vagy c lehet.
Néhány példa:
mkdir cel
cp *.py cel
cp /etc/*.conf /etc/*.cfg cel
cp *.txt /tmp
cp beszamolo.docx beszamolo_backup.docx
Ha a másolandók közt könyvtár is van, akkor a -r
kapcsolót meg kell adni. (r
mint recursive)
cp -r /etc/systemd .
Itt van jelentősége a .
speciális könyvtárnak, ami az aktuális könyvtárt jelenti (ez a parancs tehát az
aktuális könyvtárba fog másolni).
cp -r /etc/li[a-x]* /tmp
Ez a minta azokra a bejegyzésekre illeszkedik, amik első két betűje li
, amit a és x között bármi
követhet, illetve ezek után még tetszőleges karakterek következhetnek.
A cp a létező fájlt kérdés nélkül felülírja. Ha megadjuk a -i
kapcsolót, akkor minden fájl esetében rákérdez.
Törlés
Fájlok törlése az rm
paranccsal történik:
rm file1 file2 file3 ...
Könyvtár törlése esetén hibaüzenetet kapunk; ilyenkor a -r
kapcsolót is meg kell adni.
rm -r konyvtar
Itt is használhatunk helyettesítő (dzsóker, wildcard) karaktereket:
rm *.doc *.txt
A -i
kapcsolóval kiegészítve minden törlendő fájlra, könyvtárral egyenként rákérdez.
Üres könyvtár törlése
Az rmdir
paranccsal történik.
rmdir konyvtar
rmdir konyvtar1 konyvtar2 konyvtar3
rmdir ko*
A parancsnak meg tudunk adni egy, vagy több könyvtárt, illetve shell mintát is
Áthelyezés, átnevezés
Az mv
paranccsal történik. Többféle működési módja is van a szituációtól függően,
illetve áthelyezni és átnevezni is tud.
Ha két fájlt adunk meg, amik azonos könyvtárban vannak és közülük az első létezik, a második pedig nem akkor a fájlt átnevezi a könyvtáron belül.
mv regi.txt uj.txt
A regi.txt
fájl új neve ezentúl uj.txt
lesz. Ha a másodiknak megadott fájl létezik, akkor azt felülírja.
Hasonló a helyzet akkor is, ha könyvtárról van szó:
mv regi uj
A regi
ezentúl uj
néven fog szerepelni. Ha az uj
létezne, akkor a regi
-t áthelyezi
az uj
-ba.
Ha több paramétert adunk meg, akkor az utolsó paraméternek mindenképpen könyvtárnak kell lennie. A parancs ebbe a könyvtárba a többi paraméterben megadott összes fájlt és könyvtárt áthelyezi.
mv egyik.txt masik.txt akarmi.sh konyvtar1 konyvtar2 celkonyvtar
Az összes felsorolt fájl és könyvtár a celkonyvtar
könyvtárba kerül.
Shell minták természetesen ennél a parancsnál is használhatóak.
Jogosultságok kezelése
A Linux (és a Unixok) a fájlok következő jogosultságait kezelik:
- Tulajdonos
- Csoport
- Tulajdonos jogosultságai (olvasás, írás, végrehajtás)
- Csoport jogosultságai (olvasás, írás, végrehajtás)
- Mindenki más jogosultságai (olvasás, írás, végrehajtás)
Ezeket az adatokat az ls -l
Programok összekötése pipe-pal
Számos olyan parancssori program van, ami a bemenetét a standard billentyűzetről (vagy onnan is) veszi, illetve a kimenetét a standard kimenetre írja. (A standard bemenet alapesetben a billentyűzet, a standard kimenet pedig a képernyő.) Az ilyen típusú programok összekötésével komplex feldolgozás valósítható meg, elsősorban szöveges tartalmak esetében.
cat
TBD
wc
<<<<<<< HEAD
A wc
parancs megszámolja, hogy a paraméterül kapott fájlok hány sorból, szóból, illetve karakterből
állnak. Több fájl megadása esetén egy összesítést is kapunk.
wc valami.txt szoveg.txt
Kiírja, hogy a valami.txt és a szoveg.txt hány sort, szót, illetve karaktert tartalmaz.
A program működése kapcsolókkal szabályozható.
Csak a sorok számlálása:
wc -l valami.txt
Csak a szavak számlálása:
wc -w valami.txt
Csak a karaktertek számlálása:
wc -c valami.txt
head, tail
TBD
grep
parancs
Reguláris kifejezések és a A reguláris kifejezés (regular expression, regexp, regex) egy számításelméleti fogalom. Segitségével egy nyelvet (~szavak halmazát) lehet definiálni; meg tudjuk vizsgálni, hogy egy szöveg illeszkedik-e egy reguláris kifejezésre, vagyis eleme-e az általa definiált nyelvnek (halmaznak).
A legegyszerűbb reguláris kifejezések
-
A reguláris kifejezések elemi (atomi) építőegységekből épülnek fel. Ilyen egységek például az alfanumerikus karakterek (betűk, és számok), amik önmagukra illeszkednek.
-
Több atomi egység egymás után írva arra illeszkedik, amit sorban egymás után az egységek kifejeznek.
Példa:
a
Betű, önmagára illeszkedik.
b
Ez is egy betű, ez is önmagára illeszkedik.
ab
Két építőegység, ez összesen az ab
-re illeszkedik.
Tehát bármely szó (illetve betűkből, számokból és néhány egyéb jelből álló karaktersorozat) magára a szóra illeszkedik.
grep
A A grep
segítségével egy szövegből tudjuk azokat a sorokat kiszűrni, amelyik tartalmaznak egy
bizonyos reguláris kifejezést.
A példákat egy képzeletbeli pelda.txt nevű fájlon keresztül fogjuk kipróbálni.
A grep-et használhatjuk úgy is, hogy megadjuk neki a bemenetet tartalmazó fájlt:
grep regex pelda.txt
Illetve úgy is, hogy a bemenetet a standard bemenetről kapja:
valamilyen parancsok | grep regex
Egyelőre csak nagyon egyszerű reguláris kifejezéseket tudunk készíteni.
grep valami pelda.txt
egyvalami
ilyesvalami
másvalami
olyasvalami
valami
valamicske
valamilyen
valamiből
valamicskét
Kis- nagybetű érzékenység
A grep
kis-nagybetű érzékeny (case sensitive), tehát különbséget tesz a kis- és nagybetűk között.
Ennek kikapcsolása a -i
kapcsolóval történik.
grep Pista pelda.txt
Pista
De a -i kapcsoló megadásával:
grep Pista pelda.txt
pápista
sipista
trappista
utópista
Pista
eszképista
Keresés megfordítása (regex tagadása)
További fontos kapcsoló a -v
, amivel grep
azokat a sorokat fogja kiírni, amikre a megadott
reguláris kifejezés NEM illeszkedik.
grep -v a pelda.txt
Olyan sorokat fog kiírni, amikben nincs a
betű.
Horgonyok
Az eddigi példákból látható volt, hogy a megadott kifejezés bárhol
lehet a sorban (az elején, a végén, valahol középen), a grep
mindenképpen
kiírta az adott szót. A reguláris kifejezésben megadhatunk horgonyokat,
amik valahova (a sor elejére, végére) lerögzítik a reguláris kifejezés adott részét.
^
: A sor elejére rögzít$
: A sor végére rögzíŧ
Legyen a reguláris kifejezés a sor elején:
grep ^ab pelda.txt
abajgat
abakusz
abál
abált
abba
abbahagy
Legyen a végén:
grep ab$ pelda.txt
átszab
bab
beleszab
beszab
bokorbab
borhab
bútordarab
A két horgonyt egyszerre is lehet használni:
grep ^valami$ pelda.txt
valami
Karakterhalmazok
Egy konkrét karakter helyett olyan atomokat is definiálhatunk, amik többféle karakterre is illeszkedhetnek. Ezek állhatnak tartományokból, vagy felsorolt karakterekből, illetve ezek kombinációjából is
[a-z]
: a-tól z-ig bérmely karakterre illeszkedik[A-Z]
: A-tól Z-ig bármely karakterre illeszkedik[akdtx]
: Az a, k, d, t és x karakterekre illeszkedik[0-9pqfgb-h]
: Lehet számjegy, b, c, d, e, f, g, h, p, vagy q betű
Ha a -
része a listának, azt a végére kell tenni:
[0-9-]
: Számjegy, vagy kötőjel
A halmazt lehet negálni is a ^
jellel.
[^A-Z]
: Bármely karakterre illeszkedik, ami nem nagybetű.
Végezetül a .
(pont) bármely karakterre illeszkedik.
Néhány példa:
^sz..[ef][^thpza]$
: sz betű, majd két tetszőleges karakter, majd e, vagy f betű, majd egy olyan karakter, ami nem t, nem h, nem p, nem z és nem is a.^.szt
: A sor első karaktere tetszőleges lehet, majd s, z és t következik
Kvantorok
A kvantorokkal (többszörözőkkel) a reguláris kifejezés bizonyos részei (példáinkban először csak karakterek) egymás utáni előfordulásainak számát tudjuk jelölni.
atom*
: A megadott atom bármennyi (0-végtelen) darab előfordulásaatom?
: A megadott atom 0, vagy 1 darab előfordulásaatom+
: A megadott atom legalább 1 darab (1-végtelen darab) előfordulása
Kiterjesztett szintaxis
Összetett példák
ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s31f6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
[...]
Szedjük ki a releváns részeket. Kétféle információra vagyunk kiváncsiak: A számozott sorokra és az
inet
-tel kezdődőekre.
Számozott sorok:
ip addr show | grep -E '^[0-9]+:'
Az inet-es sorok:
ip addr show | grep -E '^ {4}inet '
A kettő együtt:
ip addr show | grep -E '(^[0-9]+:|^ {4}inet )'
cut
és az awk
A A cut
mezők kiírására való, feltéve hogy a mezőket valamilyen fix elválasztó karakter határolja.
(Ez alapértelmezetten a tabulátor.)
A fontosabb kapcsolók:
-d
: elválasztó karakter, delimiter-f
: mezők (field) listája
Egy vesszővel határolt táblázat második és harmadik oszlopának kinyerése például a következő módon történhet:
cat tablazat.csv | cut -d "," -f 2,3
Az awk
tulajdonképpen egy teljes értékű programnyelv, mi viszont csak a print
utasítást fogjuk használni
belőle. Például az ls -l
kimenetéből a fájlok nevének és hosszuknak a kinyerése:
ls -l | awk '{print $9 " " $5}'
Itt a " "
nélkül összefolyna a név és a hossz.
Nézzük meg a nem sokkal ezelőtti példán is. Szükségünk van mondjuk az előző blokkban tárgyalt parancs kimenetéből az IP címet tartalmazó mezőre:
ip addr show | grep -E '^ {4}inet ' | awk '{print $2}'
127.0.0.1/8
192.168.1.166/24
172.17.0.1/16
Ugyanez a cut
-tal:
ip addr show | grep -E '^ {4}inet ' | cut -d " " -f 6
Itt a 6. mezőt kellett megadni, mert az első négy szóköz önmagában 1-1 mezőnek számít.
Ezt a kimenetet például a /
jelet mint elválasztót használva tovább bonthatjuk:
ip addr show | grep -E '^ {4}inet ' | awk '{print $2}' | cut -d '/' -f 1
127.0.0.1
192.168.1.166/
172.17.0.1
Shell script alapok
Eddig a shellt interaktív módban használtuk, vagyis a parancsokat egyenként beírva hajtottuk végre. Ez egyszerűbb feladatok végrehajtárása elég is volt, azonban komplett programok (shell scriptek) írására is lehetőség van.
Először is hozzunk létre egy könyvtárt, amiben a shell scriptjeink lesznek, és lépjünk bele:
mkdir proba
cd proba
mcedit
használata
Az A shell scripteket egy fájlban kell elhelyezni, aminek a szerkesztéséhez az
mcedit
programot fogjuk használni. Legyen az első scriptünk neve elso.sh
és indítsuk el az mcedit
-et a következő módon:
mcedit elso.sh
Az mc
legfontosabb billentyűkombinációi:
- F2: mentés
- F10: kilépés
- Ctrl-u: visszavonás
- F8: kijelölt rész, vagy aktuális sor törlése
Az első script
A shell scripteket a következő sorral kell kezdeni:
#!/bin/bash
Ez jelzi, hogy a scriptet a bash
fogja végrehajtani. (Hasonlót láthatunk Python és
más interpretált nyelvek esetén is.)
Az ezt követő sorok szekvenciaként végrehajtódnak és többek közt az előzőekben használt parancsok is használhatóak. Legyen az első programunk a következő:
#!/bin/bash
echo "Hello, World!"
Mentsük el (F2), majd adjunk rá futási jogot:
chmod a+x elso.sh
Egy apró megjegyzés: Az mcedit
minden mentésnél azokat a jogosultságokat fogja visszaállítani,
amiket akkor talált, amikor a fájlt megnyitotta. Az első létrehozáskor célszerű kilépni a
szövegszerkesztőből, chmod
-olni, majd újra megnyitni a file-t.
Futtatni az elérési út megadásával tudjuk, például ha az aktuális konyvtárban van a fájlunk:
./elso.sh
De az összetettebb (akár relatív, akár abszolút elérési utak is működnek:
/home/abc123/proba/elso.sh
~/proba/elso.sh
A program a Hello, World! szöveget fogja kiírni.
Adatbekérés
A billentyűzetről a read
paranccsal kérhetünk be adatokat. A read
után egy,
vagy több változót kell megadni, amikbe a beolvasott adatok kerülnek.
A read
mindig egy sort olvas be.
- Ha egy változót adunk meg, akkor a teljes beolvasott sor abba a változóba kerül.
- Két változó esetén az első szó az első változóba, a maradék pedig a második változóba kerül.
- Három változó esetén az első szó az első változóba, a második szó a másodikba, minden más a harmadikba kerül.
- Stb.
A read
-et használhatjuk paraméterek nélkül is. Ilyenkor a beolvasott adatokat eldobja.
#!/bin/bash
echo "Melyik file-t toroljem?"
read fn
rm $fn
A fenti program a beolvasott nevű fájlt törli.
A read
-et egy másik program kimenetének soronként történő beolvasására is használhatjuk. Erről
majd később.
For
ciklus
Ciklust többek közt a for
segíŧségével szervezhetünk a következő módon:
for valtozo in ertek1 ertek2 ertek3 [...]
do
ciklusmag
done
A valtozo
sorban felveszi az ertek1
, ertek2
, ... értékeket és minden esetben lefut a ciklusmag.
Azonban a shell, mint fentebb már megfigyeltük, a shell mintákat behelyettesíti, így például a
*
helyére az aktuális könyvtárban levő bejegyzések (fájlok, könyvtárak) kerülnek:
for fn in *
do
wc -l $fn
done
Ez a program az aktuális könyvtárban található összes fájlon, könyvtáron végigmegy és
mindegyikre lefuttatja a wc -l
parancsot.
if
)
Elágazás (Nézzük meg az if
használatát egy példán keresztül:
for fn in *
do
echo "A file neve:"
echo "$fn"
if [ -f "$fn" ]
then
echo "Ez egy sima file."
fi
echo
done
[
parancs
A A fenti szerkezetben a [ -f "$fn" ]
egy parancs, aminek az eredménye alapján hajtja
végre az if
a then
, vagy az opcionális else
ágat. A parancs
eredménye nem azonos a parancs kimenetével. (Ezt a számot
a $?
változó tartalmazza. Itt a 0
jelentése az igaz és
minden más a hamis.)
A [
parancsot használhatjuk például:
- Stringek néhány tulajdonságának vizsgálatára:
[ -z STR ]
Az STR string hossza nem nulla.[ -n STR ]
Az STR string hossza nulla.[ STR1 = STR2 ]
Az STR1 és STR2 stringek egyenlőek.- Számok összehasonlítására:
[ A -eq B ]
Az A és B számok egyenlőek.[ A -ne B ]
Az A és B számok egyenlőek.[ A -lt B ]
A < B[ A -gt B ]
A > B[ A -le B ]
A <= B[ A -ge B ]
A >= B- Fájlok bizonyos tulajdonságainak vizsgálatára:
[ -e FILE ]
A FILE létezik.[ -f FILE ]
A FILE létezik és sima fájl.[ -d FILE ]
A FILE létezik és könyvtár.
További lehetőségek: man [
, vagy man test
.
A fenti példában tehát az if
után szereplő kifejezés tulajdonképpen egy parancs.
Az if
feltétel része bármilyen más parancs is lehet.
if
, elif
és else
Az else
ág akkor fog lefutni, ha a megadott feltétel nem teljesül. Az elif
a más nyelvekben
megszokott else if
, vagy elsif
megfelelője. Emellett
az elágazásokat egymásba is lehet ágyazni. Nézzünk egy példát:
#!/bin/bash
for x in *
do
echo "A bejegyzes neve:"
echo $x
if [ -e $x ]
then
if [ -f $x ]
then
echo "A bejegyzes egy sima file."
elif [ -d $x ]
then
echo "A bejegyzes egy konyvtar."
else
echo "A bejegyzes se nem sima file, se nem konyvtar."
else
echo "A bejegyzes nem letezik."
fi
echo
done
expr
használatával és anélkül
Aritmetika Adjuk össze az összes .txt
-re végződő fájl sorainak számát. Ehhez a következő feladatokat
kell megoldanunk:
- Végig kell mennünk a fájlokon
- Ki kell nyernünk az adott fájl sorainak számát és eltárolni azt egy változóban.
- Össze kell adni a számokat.
A fájlokon már végig tudunk menni a tanultak alapján:
for fn in *.txt
do
echo $fn
done
expr
parancs
Az Az expr
paranccsal aritmetikai műveleteket végezhetünk egész számokon:
expr 1 + 2
expr 10 - 5
expr 8 / 3
expr 2 \* 3
expr 10 % 4
A szorzáshoz használt *
-ot a shell saját maga is értelmezi, ezért azt escape-elni kell (a \
jel segíŧségével). A %
jel osztási maradékot számol. Az expr
csak egész számokkal tud számolni.
$()
szintaxis (parancs-behelyettesítés)
A A $()
-be írt parancsot a parancsértelmező lefuttatja és a program kimenetét behelyettesíti. Próbáljuk ki a wc
és az expr
parancsokkal:
sor=$(cat $fn | wc -l)
Ezzel az fn
változóban tárolt nevű fájl sorainak száma bekerül a sor
változóba.
osszes=$(expr $osszes + $sor)
Ezzel pedig az osszes
változó értékét megnöveljük a sor
változó értékével. (Az osszes
változót
induláskor nullázni kell.)
A teljes program
A teljes program tehát így néz ki:
osszes=0
for fn in *.txt
do
sor=$(cat $fn | wc -l)
osszes=$(expr $osszes + $sor)
done
echo $osszes
while
ciklus
A TBD
while
és read
segítségével
Több sornyi adat beolvasása TBD
while read fn
do
true
done
Keresés a fájlok között
Keresni a find
paranccsal tudunk. Paraméterek nélkül az aktuális konyvtárban keres, minden típusú
bejegyzést, a találatokat egyszerűen kiírja.
Megadhatunk neki például egy könyvtárt, ahol keresni fog:
find KONYVTAR
Megadhatjuk a keresendő bejegyzések típusát a -type
kapcsolóval (f
: fájl, d
: könyvtár):
find -type f
find -type d
Az első csak a fájlokat, a második csak a könyvtárakat fogja keresni.
Illetve megadhatunk egy mintát, amire a fájl (vagy könyvtár) nevének kell illeszkednie, a -name
kapcsolóval. Itt shell mintát (tehát NEM reguláris kifejezést!) kell használni.
find . -type f -name "*.txt"
A fenti parancs az aktuális könyvtárban (.
) fog .txt
végződésű fájlokat keresni.
A -name
kis-nagybetű érzékeny. Ennek a nem kis-nagybetű érzékeny változata a -iname
.
A find
használata a -exec
paraméter használatával, illetve a kimenetek további feldolgozásával
válik igazán sokoldalúvá. A -exec
segítségével a find
a megtalált fájlokat, könyvtárakat
nem egyszerűen kiírja, hanem minden egyes találatra lefuttat egy parancsot. Használata a következő:
find KONYVTAR -type TIPUS -name MINTA -exec PARANCS "{}" \;
A megtalált fájl, vagy könvytár nevét a "{}"
helyére helyettesíti a parancs.
find . -type f -name "*.txt" -exec ls -l "{}" \;
A fenti parancs az aktuális könyvtárban megkeres minden .txt
-re végződő fájlt
és mindegyiken lefuttatja az ls -l
parancsot (tehát minden fájlról egy részletes
listát kapunk a jogosultságokkal, a mérettel stb.).
find /etc -type f -name "*.conf" -exec wc -l "{}" \;
A fenti parancs a /etc
könyvtárban megkeres minden .conf
-ra végződő fájlt
és lefuttatja rajtuk a wc -l
parancsot (ami kiírja, hogy melyik fájl hány sorból áll).
Ezeket a kimeneteket aztán fel is dolgozhatjuk.
find /usr -type f -name "*" -exec ls -l "{}" \; | grep '^...[^x]' | wc -l
A fenti parancs megszámolja, hogy a /usr
könyvtárban hány olyan fájl van, amire
a tulajdonosának nincs futtatási joga.
Parancssori paraméterek kezelése
A programunknak megadhatunk paramétereket (argumentumokat) is, a következő módon:
./scriptem.sh elso masodik harmadik
Ekkor az 1. argumentum a $1
, a második a $2
, a harmadik a $3
stb. változóban lesz.
Legyen az első paraméter egy könyvtár elérési útvonala, a második paraméter pedig egy fájlkiterjesztés
Összetettebb shell script elemek
if
használata más feltételekkel
Az Az if
parancsot nem csak a [
-es szerkezettel tudjuk használni, hanem
tulajdonképpen bármilyen más programmal is, aminek az eredménye alapján
az if
a then
, vagy az else
ágban levő utasításokat tudja végrehajtani.
if
használata a grep
-pel
Az Készítsünk egy fej, vagy írás programot, ami véletlenszerűen
ki tudja írni, hogy FEJ, vagy IRAS. Ehhez véletlenszámokat
kell generálni. Ez a RANDOM
változó kiolvasásával tehető meg.
A RANDOM
változó minden kiolvasáskor egy véletlenszerű, 0 és 32767 közötti egész számot ad.
Ebből például úgy tudunk fejet, vagy írást csinálni, hogy a páros
számokhoz a fejet, a páratlanokhoz az írást rendeljük hozzá.
Tehát ha a szám utolsó számjegye 0, 2, 4, 6, vagy 8, akkor
az eredmény fej, egyébként írás. Ezt a grep
paranccsal
és egy reguláris kifejezéssel tudjuk eldönteni.
A reguláris kifejezésünk illeszkedjen mondjuk a fejre, tehát arra
az esetre, amikor a szám a 0, 2, 4, 6 és 8 számok valamelyikére
végződik. A megoldás: '[02358]$'
. A grep
-hez szükséges még a -q
kapcsoló is, hogy magát a számot ne írja ki, csak döntse el, hogy
illeszkedik-e a mintára, vagy nem. A teljes program:
if echo $RANDOM | grep -q '[02468]$'
then
echo "FEJ"
else
echo "IRAS"
fi
Készítsünk olyan programot, ami végighalad az összes fájlon és megnézi,
hogy mely fájlok első sora #/bin/bash
. (Rekurzív keresés nem szükséges.)
for fn in *
do
if head -n 1 $fn | grep -q '^#!/bin/bash$'
then
echo $fn
fi
done
Tetszőlegesen sok parancsori paraméter (argumentum) kezelése
Eddigi ismereteink szerint fix számú argumentumot tudtunk kezelni shell scriptjeinkben. Lehetőség van viszont arra is, hogy tetszőleges számú paramétert feldolgozzunk. Nézzük először a következő programot:
echo "Parameterek szama: $#"
echo "Elso parameter: $1"
echo "Masodik parameter: $2"
echo "Harmadik parameter: $3"
echo
shift
echo "Parameterek szama: $#"
echo "Elso parameter: $1"
echo "Masodik parameter: $2"
echo "Harmadik parameter: $3"
echo
shift
echo "Parameterek szama: $#"
echo "Elso parameter: $1"
echo "Masodik parameter: $2"
echo "Harmadik parameter: $3"
echo
shift
echo "Parameterek szama: $#"
echo "Elso parameter: $1"
echo "Masodik parameter: $2"
echo "Harmadik parameter: $3"
Futtassuk a programunkkat négy parancssori paraméterrel:
./scriptem.sh elso masodik harmadik negyedik
Minden shift
parancs után a paraméterlista eggyel elcsúszik. Az első helyre az eddigi második
kerül, a második helyre az eddigi harmadik stb. Az eddigi első paraméter eltűnik, a paraméterek száma ($#
)
eggyel csökken.
Ezek után már készíthetünk egy olyan programot, ami végigmegy az összes paraméteren:
while [ $# -ne 0 ]
do
aktualis=$1
echo $aktualis
shift
done
A programban a $#
a paraméterek aktuális számát jelenti. A ciklus addig fog működni, amíg ez 0-ra nem csökken.
A $1
változón egyesével minden paraméter végighalad. A programban az echo
csak egy példa. Értelemszerűen
bármilyen módon felhasználhatjuk a paramétereket.
Azt is megtehetjük, hogy az első (vagy az első kettő stb.) paramétert külön kezeljük, illetve nem csak egyesével tudunk végiglépkedni a paramétereken, hanem kettesével, hármasával stb. is.
Készítsünk egy programot, ami tetszőlegesen sok paramétert fogad és a következő módon működik. Minden
paraméter egy-egy fájl nevét adja meg. Minden fájlról készítsünk biztonsági másolatot a backup
nevű
könyvtárban.
while [ $# -ne 0 ]
do
fn=$1
cp $fn backup
shift
done
Bővítsük ki ezt a programot úgy, hogy ne a backup
, hanem az első paraméterben megadott könyvtárba
készüljenek a biztonsági mentések. A program vizsgálja meg azt is, hogy ez a könyvtár létezik-e.
Ha nem létezik, hozza létre. Ha létezik ilyen néven bejegyzés, de az nem könyvtár, akkor
adjon hibaüzenetet és lépjen ki. Programunk a következő módon fog kinézni:
cel=$1
shift
if [ -d $cel ]
then
echo "A $cel letezik."
elif [ -e $cel ]
then
echo "A $cel nem konyvtar, nem hozhato letre a biztonsagi mentes."
exit
else
echo "Nem letezik $cel neven bejegyzes, igy ilyen neven letrehozunk egy konyvtarat."
mkdir $cel
fi
while [ $# -ne 0 ]
do
fn=$1
cp $fn $cel
shift
done
A programban az első paramétert egy külön változóban eltároljuk, majd a shift
utasítás után úgy
tudjuk kezelni a változókat, mint az eddigiekben.
Egy parancs kimenetének soronként történő feldolgozása
Tegyük fel, hogy egy program, például egy megfelelően felparaméterezett find
által kiírt adatokon szeretnénk egyesével végigmenni. Ehhez a read
-et tudjuk
felhasználni úgy, hogy egy pipe segítségével az adott parancsot egy while read
szerkezetbe kötjük be.
Keressük meg azokat a shell scripteket a proba
könyvtárban, amik NEM a #!/bin/bash
sorral kezdődnek.
find . -type f -name "*.sh" | \
while read fn
do
if grep -vq '^#!/bin/bash$'
then
echo
fi
done