Ghidul începătorului pentru Shell Scripting 2 For Loops
Dacă doriți să vă creați un geek cred, alăturați-ne pentru a doua tranșă din seria noastră de scripting shell. Avem câteva corecții, câteva îmbunătățiri ale scenariului de săptămâna trecută și un ghid despre looping pentru cei neinițiați.
Datacp Script Revisited
În prima parte a ghidului de scripting pentru shell, am creat un script care a copiat un fișier într-un director de rezervă după ce a adăugat data până la sfârșitul numelui de fișier.
Samuel Dionne-Riel a subliniat în comentariile că există o modalitate mult mai bună de a ne ocupa de referințele noastre variabile.
Argumentele sunt separate în spațiu în shell-ul bash, acesta va tokenize când există un spațiu în comanda extinsă rezultată. În scenariul tău,
cp $ 1 $ 2. $ date_formatted
va funcționa conform destinației atâta timp cât variabilele extinse nu au spații în ele. Dacă numiți scenariul în felul următor:datecp "numele meu vechi" "noul meu nume"
extinderea va duce la această comandă:cp noul meu nume vechi name.the_date
care de fapt are 6 argumente.Pentru a aborda corect această problemă, ultimul rând al scriptului ar trebui să fie:
cp "$ 1" "$ 2. $ date_formatted"
După cum puteți vedea, schimbarea liniei scriptului nostru de la:
cp -iv $ 1 $ 2. $ date_formatted
la:
cp -iv "$ 1" "$ 2". $ date_formatted
va avea grijă de această problemă atunci când se utilizează script-ul pe fișiere care au spații în nume. Samuel, de asemenea, subliniază că, atunci când copiați și lipiți codul de pe acest site (sau internetul în general), asigurați-vă că înlocuiți liniuțele și citatele potrivite pentru cele "tipografice mai bune" care le înlocuiesc adesea. De asemenea, vom face mai multe pentru a vă asigura că codul nostru este mai prietenos cu copierea / lipirea. ;-)
Un alt comentator, Myles Braithwaite, a decis să ne extindă scenariul, astfel încât data să apară înaintea extensiei fișierului. Deci, în loc de
tastyfile.mp3.07_14_11-12.34.56
am obține acest lucru:
tastyfile.07_14_11-12.34.56.mp3
care sfârșește prin a fi un pic mai convenabil pentru majoritatea utilizatorilor. Codul lui este disponibil pe pagina GitHub. Să aruncăm o privire la ceea ce folosește pentru a distruge numele fișierului.
date_formatted = $ (data +% Y-% m-% d_% H.% M% S)
file_extension = $ (echo "$ 1" | awk -F. 'print $ NF')
file_name = $ (numele de bază $ 1. $ file_extension)cp -iv $ 1 $ file_name- $ data_formatted. $ file_extension
Am schimbat formatul un pic, dar puteți vedea că Myles declară funcția dată în Linia 1. În Linia 2, cu toate acestea, el folosește comanda "ecou" cu primul argument al scriptului pentru a ieși numele fișierului. El folosește comanda țeavă pentru a prelua ieșirea și a le folosi ca intrare pentru următoarea parte. După conductă, Myles apelează comanda "awk", care este un program puternic de scanare a modelului. Folosind flagul -F, el spune comanda că următorul caracter (după un spațiu) este ceea ce va defini "separatorul de câmp". În acest caz, este o perioadă.
Acum, vedeți un fișier numit "tastyfile.mp3" ca fiind compus din două câmpuri: "tastyfile" și "mp3". În cele din urmă, el folosește
'print $ NF'
pentru a afișa ultimul câmp. În cazul în care fișierul dvs. are mai multe perioade - de a face awk a vedea mai multe câmpuri - va afișa doar ultima, care este extensia de fișier.
În linia 3, el creează o nouă variabilă pentru numele fișierului și folosește comanda "basename" pentru a face referință la toate în $ 1 cu exceptia extensia de fișier. Aceasta se face folosind numele de bază și oferindu-i $ 1 ca argument, apoi adăugând un spațiu și extensia fișierului. Extensia de fișier este adăugată automat din cauza variabilei care face referire la Linia 2. Ce ar face acest lucru este să luați
tastyfile.mp3
și transformați-o în
tastyfile
Apoi, în ultima linie, Myles a pus împreună comanda care va scoate totul în ordine. Rețineți că nu există nici o referință la $ 2, un al doilea argument pentru script. Acest script special va copia fișierul menționat în directorul dvs. curent. Locul de muncă foarte bun Samuel și Myles!
Running Scripts și $ PATH
De asemenea, menționăm în articolul nostru de bază că script-urile nu au voie să fie menționate ca comenzi în mod implicit. Adică trebuie să indicați calea scenariului pentru al rula:
./ script
~ / Bin / script
Dar, prin plasarea scripturilor în ~ / bin /, puteți doar să le scrieți numele de oriunde pentru a le face să ruleze.
Comenterii au petrecut ceva timp dezbatând cât de corect a fost acest lucru, deoarece nici un distro Linux modern nu creează acel director în mod implicit. În plus, nimeni nu îl adaugă implicit la variabila $ PATH, ceea ce este necesar pentru ca script-urile să fie executate ca și comenzi. Am fost puțin nedumerit, deoarece după verificarea variabilei mele $ PATH, comentatorii au avut dreptate, dar scripturile de asteptare încă lucrau pentru mine. Am aflat de ce: multe distribuții moderne Linux creează un fișier special în directorul de domiciliu al utilizatorului - .profile.
Acest fișier este citit de bash (cu excepția cazului în care .bash_profile este prezent în directorul de domiciliu al utilizatorului) și în partea de jos, există o secțiune care adaugă folderul ~ / bin / la variabila $ PATH, dacă există. Deci, acel mister este clarificat. Pentru restul seriei, voi continua să plasez script-uri în directorul ~ / bin /, deoarece acestea sunt scripturi de utilizator și ar trebui să poată fi gestionate de utilizatori. Și, se pare că nu trebuie să ne mândrim cu variabila $ PATH cu mâna pentru ca lucrurile să funcționeze.
Repetarea comenzilor cu buclă
Să ajungem la unul dintre cele mai utile instrumente din arsenalul geek pentru a face față sarcinilor repetitive: bucle. Astăzi, vom discuta despre "buclele".
Schița de bază a for-buclă este după cum urmează:
pentru VARIABLE in LIST; do
command1
comanda2
...
commandn
Terminat
VARIABLE poate fi orice variabilă, deși cel mai adesea "i" este folosit convențional. LIST este o listă de articole; puteți specifica mai multe elemente (separându-le de un spațiu), indicați un fișier text extern sau utilizați un asterisc (*) pentru a denumi orice fișier din directorul curent. Comenzile listate sunt indentate prin convenție, deci este mai ușor să vezi cuiburile - punerea buclelor în bucle (astfel încât să puteți bucle în timp ce bucla).
Deoarece listele folosesc spațiile ca delimitatori - adică un spațiu înseamnă o mutare la următorul element din listă - fișierele care au spații în nume nu sunt foarte prietenoase. Deocamdată, hai să rămânem la lucru cu fișiere fără spații. Să începem cu un script simplu pentru a afișa numele fișierelor din directorul curent. Creați un script nou în folderul dvs. ~ / bin / intitulat "loopscript". Dacă nu vă amintiți cum să faceți acest lucru (inclusiv marcarea acestuia ca executabil și adăugarea hack-ului de tip hash), consultați articolul de bază al scripting-ului bash.
În acesta, introduceți următorul cod:
pentru i în item1 element2 element3 element4 element5 element6; do
echo "$ i"
Terminat
Când rulați scriptul, ar trebui să obțineți doar elementele listate ca ieșire.
Destul de simplu, nu? Să vedem ce se întâmplă dacă schimbăm puțin lucrurile. Schimbați-vă scenariul astfel încât să spuneți acest lucru:
pentru că eu în *; do
echo "$ i"
Terminat
Când executați acest script într-un dosar, trebuie să obțineți o listă de fișiere pe care le conține ca ieșire.
Acum, să schimbăm comanda ecou în ceva mai util - să zicem, comanda zip. Adică, vom adăuga fișiere într-o arhivă. Și, hai să luăm niște argumente în amestec!
pentru i în $ @; do
zip arhiva "$ i"
Terminat
Este ceva nou! "$ @" Este o scurtătură pentru "$ 1 $ 2 $ 3 ... $ n". Cu alte cuvinte, este lista completă a tuturor argumentelor pe care le-ați specificat. Acum, urmăriți ce se întâmplă când rulez scriptul cu mai multe fișiere de intrare.
Puteți vedea fișierele din dosarul meu. Am executat comanda cu șase argumente, iar fiecare fișier a fost adăugat la o arhivă cu cifre numită "archive.zip". Ușor, corect?
Buclele sunt destul de minunate. Acum puteți executa funcții lot pe listele de fișiere. De exemplu, puteți să copiați toate argumentele scriptului într-o arhivă pe zip, să mutați originalele într-un alt folder și să copiați automat fișierul zip pe un computer la distanță. Dacă configurați fișiere cheie cu SSH, nu veți mai fi nevoie să introduceți parola și chiar puteți spune scriptului să șterge fișierul zip după încărcarea lui!
Folosirea for-buclelor face mai ușor să faceți o grămadă de acțiuni pentru toate fișierele dintr-un director. Puteți să îmbinați o mare varietate de comenzi împreună și să folosiți foarte ușor argumentele pentru a crea o listă on-the-fly și aceasta este doar vârful aisbergului.
Bash scripteri, aveți vreo sugestie? Ați făcut un script util care utilizează buclele? Doriți să vă împărtășiți gândurile seriei? Lăsați câteva comentarii și ajutați-i pe ceilalți începători de scripting!