Džokeri i navodnici — kako shell proširuje šablone
Kad kucaš ls *.txt, komanda ls nikada ne vidi
zvezdicu. Shell je razreši pre nego što pokrene komandu i prosledi joj
gotov spisak imena fajlova. To je jedna rečenica koja objašnjava skoro sve
čudne situacije sa džokerima — i kad rade, i kad ne rade.
Ova lekcija pokriva džokere (*, ?,
[ ]) i tri načina da shell-u kažeš da ne dira ono što si
napisao (navodnici i kosa crta).
Ko zapravo radi posao
Pretpostavimo ovaj direktorijum:
$ ls beleske.txt izvestaj-2025.pdf slika10.png skripta.sh izvestaj-2024.pdf slika1.png slika2.png
Kad kucaš ls *.png, dešava se ovo:
- Shell pogleda direktorijum i pronađe imena koja odgovaraju šablonu.
- Shell zameni
*.pngtim imenima, sortiranim po abecedi. - Tek onda pokreće
ls slika1.png slika10.png slika2.png.
Najlakši način da to vidiš svojim očima je komanda echo — ona samo ispiše ono što joj shell prosledi:
$ echo *.png slika1.png slika10.png slika2.png
Zapamti ovo pravilo: pre svake opasne komande sa džokerom, prvo
kucaj echo sa istim šablonom. Ako je ispis onaj koji očekuješ,
zameni echo sa rm ili mv. Ovo je
navika koja spasava podatke.
Zvezdica: bilo koji broj znakova
* se poklapa sa bilo kojim nizom znakova — uključujući i
prazan niz.
$ ls *.pdf izvestaj-2024.pdf izvestaj-2025.pdf $ ls izvestaj* izvestaj-2024.pdf izvestaj-2025.pdf $ ls *e* beleske.txt izvestaj-2024.pdf izvestaj-2025.pdf
Pošto se poklapa i sa nulom znakova, ls skripta* pronaći će i
fajl koji se zove tačno skripta.
Upitnik: tačno jedan znak
? stoji za tačno jedan bilo koji znak — ni manje, ni više.
Ovo je razlika koja se najlakše zapamti kroz primer:
$ ls slika?.png slika1.png slika2.png $ ls slika*.png slika1.png slika10.png slika2.png
slika10.png ima dva znaka između „slika" i „.png", pa ga
? preskače. Ako ti treba baš dvocifreno:
ls slika??.png.
Uglaste zagrade: jedan znak iz skupa
[ ] je precizniji upitnik — poklapa jedan znak, ali samo iz
liste koju ti navedeš.
$ ls izvestaj-202[45].pdf izvestaj-2024.pdf izvestaj-2025.pdf $ ls slika[12].png slika1.png slika2.png
Unutar zagrada radi i opseg, sa crticom:
[0-9]— bilo koja cifra[a-z]— bilo koje malo slovo[a-zA-Z0-9]— slovo ili cifra
Uzvičnik (ili kapica) na početku znači negaciju — „bilo koji znak osim ovih":
$ ls slika[!1].png slika2.png
[^1] radi isto. Obrati pažnju: negira se samo jedan znak, ne
ceo ostatak imena — zato slika10.png ovde ne prolazi (ima dva
znaka posle „slika").
Vitičaste zagrade: proširenje liste
{ } tehnički nije džoker, jer ne gleda šta postoji na
disku — samo generiše kombinacije teksta. Zato radi i kad fajlovi tek
treba da nastanu:
$ echo fajl{1,2,3}.txt
fajl1.txt fajl2.txt fajl3.txt
$ touch log-{01..05}.txt
$ ls log*
log-01.txt log-02.txt log-03.txt log-04.txt log-05.txt
Najkorisniji trik u praksi — brza rezervna kopija fajla pre nego što ga menjaš:
$ cp /etc/ssh/sshd_config{,.bak}
Shell to proširi u cp /etc/ssh/sshd_config
/etc/ssh/sshd_config.bak, jer je prva stavka u listi prazna. Više o
kopiranju ima na stranici cp.
Šta džokeri ne rade
Ne hvataju skrivene fajlove
Imena koja počinju tačkom zvezdica namerno preskače:
$ ls -a . .. .bashrc .profile beleske.txt skripta.sh $ echo * beleske.txt skripta.sh
Zato cp * /backup/ neće prekopirati tvoja podešavanja. Ako ti
trebaju i skriveni fajlovi, koristi .[!.]* — a nikako
rm -r .*, jer taj šablon zahvata i .., odnosno
roditeljski direktorijum.
Ne prelaze preko kose crte
* se ne poklapa sa /. ls *.txt gleda
samo tekući direktorijum. Za jedan nivo dublje treba
ls */*.txt. Za rekurzivnu pretragu kroz celo stablo koristi se
find, a ne džoker.
Kad nema poklapanja, shell ne dira šablon
Ovo je izvor jedne od najčešćih zbunjujućih poruka:
$ ls *.doc ls: cannot access '*.doc': No such file or directory
Nema nijednog .doc fajla, pa shell nema šta da zameni i
prosleđuje *.doc doslovno. ls onda pokušava da
otvori fajl koji se bukvalno zove „zvezdica tačka doc". Poruka nije bug —
ona ti govori da šablon nije pogodio ništa.
Navodnici: kako da shell ostavi tekst na miru
Postoje tri načina da se zaštiti tekst, i razlikuju se po tome koliko strogo štite.
1. Jednostruki navodnici — sve doslovno
$ echo 'Cena je $5 i pise se * ovako' Cena je $5 i pise se * ovako
Unutar ' ' ništa nema posebno značenje. Jedino što ne može da
stane unutra jeste sam apostrof.
2. Dvostruki navodnici — čuvaju razmake, ali ne i promenljive
$ echo "Danas je $(date +%d.%m.%Y)" Danas je 22.08.2026. $ echo "Cena je $5" Cena je
Drugi primer iznenađuje početnike: unutar " " znak
$ i dalje radi, a $5 je peti argument skripte —
prazan. Ako želiš da se ispiše dolar, treba 'Cena je $5' ili
"Cena je \$5".
Ukratko: dvostruki navodnici gase džokere i razmake, ali ostavljaju
$, ` i \ aktivnima.
3. Obrnuta kosa crta — štiti tačno jedan znak
$ touch moj\ fajl.txt $ echo 3 \* 4 3 * 4
Tri greške koje svi naprave bar jednom
Fajl sa razmakom u imenu
$ rm moj fajl.txt rm: cannot remove 'moj': No such file or directory rm: cannot remove 'fajl.txt': No such file or directory
Shell je razmak protumačio kao granicu između dva argumenta. Ispravno je
rm "moj fajl.txt" ili rm moj\ fajl.txt. Isto važi i
za promenljive u skriptama — uvek pod dvostrukim navodnicima:
$ fajl="moj fajl.txt" $ ls $fajl ls: cannot access 'moj': No such file or directory $ ls "$fajl" moj fajl.txt
Šablon koji treba da vidi sama komanda
$ find . -name *.txt find: paths must precede expression: 'log-02.txt'
Shell je proširio *.txt u spisak fajlova pre nego što je
find uopšte pokrenut, pa je find dobio gomilu
imena tamo gde očekuje jedan obrazac. find ima sopstveni sistem
šablona i traži da mu tekst stigne netaknut:
$ find . -name '*.txt' ./log-01.txt ./log-02.txt ./beleske.txt
Isto pravilo važi i za grep: obrazac ide pod navodnike, i zato što sadrži specijalne znake i zato što često ima razmake.
$ grep 'connection refused' /var/log/syslog
Razmak na pogrešnom mestu
$ rm * .txt
Namera je bila rm *.txt. Ono što se zaista izvršilo jeste
rm * — brisanje svega u direktorijumu — a zatim još i pokušaj
brisanja fajla imenom .txt. Ovo je tačno onaj slučaj u kome
navika sa echo iz uvoda spasava dan. Detaljnije o opasnostima
brisanja ima na stranici rm.
Bonus: fajl koji počinje crticom
Ako se fajl zove -izvestaj.txt, komanda ga tumači kao
opciju:
$ rm -izvestaj.txt rm: invalid option -- 'i'
Rešenje je da mu daš putanju koja ne počinje crticom, ili da odvojiš
opcije od argumenata sa --:
$ rm ./-izvestaj.txt $ rm -- -izvestaj.txt
Kratka referenca
*— bilo koji broj znakova, uključujući nijedan?— tačno jedan znak[abc]— jedan znak iz skupa[a-z],[0-9]— jedan znak iz opsega[!abc]— jedan znak koji nije iz skupa{a,b,c}— generiše listu, ne gleda disk'tekst'— sve doslovno"tekst"— doslovno osim$,`,\\z— štiti tačno jedan znak
Vežba
Napravi prazan direktorijum i u njemu ovo:
$ mkdir vezba && cd vezba
$ touch izvestaj-{2023,2024,2025}.pdf slika{1,2,10}.png beleske.txt .skriveno
Pa proveri da li možeš, koristeći echo, da napišeš šablon
koji pogađa:
- samo PDF fajlove iz 2024. i 2025. godine
- samo
slika1.pngislika2.png, ali ne islika10.png - sve osim PDF fajlova
Za treći zadatak ti treba nešto što nismo pominjali — pogledaj u
man stranici za bash odeljak
Pattern Matching i pojam extglob. Traženje odgovora u
dokumentaciji je deo vežbe.
Kad ti džokeri uđu u prste, sledeći korak je da razumeš gde se ti fajlovi uopšte nalaze: Direktorijumi i fajlovi Linux sistema.
Cela lekcija je deo vodiča Linux osnove.
Comments
Post a Comment