
Recentemente mi è capitato di dover spiegare ad un amico come funziono gli script shell linux. Uno script shell è utile quando bisogna fare delle operazioni ripetitive, pianificare delle operazioni da eseguire periodicamente, estendere le funzionalità di linux, ecc. Cercherò in questo articolo di spiegare un po' le basi della "programmazione" con la shell linux. Non è niente di trascendentale o tremendamente complicato, basta solo un po' di ragionamento e pazienza
Le basi
Come prima cosa bisogna creare un nuovo file "scrip_esempio.sh" e dare ad esso i permessi di esecuzione (tramite interfaccia o con "chmod +x"), l'estensione ".sh" non è strettamente necessaria ma ci permette di riconoscere fin da subito i file che contengono script. La prima istruzione che andremo ad inserire dentro il notro file stabilisce quale shell dobbiamo eseguire, ed è proprio questa istruzione che fa "vivere" il nostro script shell,
#!/bin/bash
questo concetto per i neofiti sembra abbastanza assurdo, ma volendo semplificare le cose, basta pensare che la prima istruzione serve ad indicare il "programma" che interpreterà il nostro script. In molti script si può trovare anche la seguente dichiarazione: "#!/bin/sh"; la shell "sh", senza scatenare guerre di religione, è ormai obsoleta, meglio usare "bash" che ha un set di istruzioni molto più ampio rispetto alla precedente, quindi, se in caso uno script non esegue alcune operazioni o non riconosce alcuni comandi controllate con quale "programma" state eseguendo lo script.
Come concetto di base uno script shell permette di eseguire una sequenza di "comandi", programmi o altri script, organizzati in strutture usate nella programmazione. Quindi una conoscenza base dei comandi è necessaria, comunque in questa guida spiegherò passo passo quello che andremo a fare, invece, per chi vuole approfondire può consultare i seguenti link:
- http://www.di.unito.it/~vercelli/works/command-summary.html
- http://linux.collectiontricks.it/wiki/Guida_ai_comandi_base_della_shell_in_GNU/Linux
- http://it.wikipedia.org/wiki/Categoria:Comandi_Unix/Linux
Tutti i commenti sono preceduti dal simbolo cancelletto
#tutta la linea è commentata cd cartella #tutto dopo il cancelletto è un commento
Vediamo ora un un semplice esempio
#!/bin/bash #mi sposto nella cartella documenti, il simbolo "~" indica l'home directory dell'utente che esegue lo script cd ~/Documenti #mostro il contenuto con informazioni sui permessi, la data e il peso ls -lah
Variabili, cicli, loop, ecc.
Oltre che lanciare i comandi singoli possiamo eseguire dei loop, cicli e condizioni, una rapida carrellata:
#inizializza una variabile variabile="variabile"
#stampa una variabile echo $variabile
#salva output di un programma in una variabile variabile=$(ls /home/Utente/Scrivania)
#preleva input utente e lo salva in una variabile e poi lo stampa echo -e "Inserisci una parola: \c" read parola echo $parola
#preleva input utente e lo salva in una lista (array) e poi stampa gli elementi echo -e "Inserisci delle parole:" #l'opzione -a inserisce l'input in array read -a parola #stampo in modo grossolano, si dovrebbe fare un ciclo for ma è un esempio echo "hai inserito: ${parola[0]}, ${parola[1]}, ${parola[2]}"
#un ciclo if elseif ed else if [ $variabile = $condizione ]; then echo "condizione true" elif [ $variabile = $condizione ]; then echo "condizione true di elseif" else echo "condizione else" fi
#un ciclo while while [ $loop == "true" ] do echo "questo è un loop" done
#Dichiaro una lista (array) di 4 elementi, NB nota le virgolette lista=( Debian Redhat 'Ubuntu 12.04' 'Linux 3.2' ) # recupero il numero degli elementi n_elementi=${#lista[@]} # for loop for (( i=0;i<$n_elementi;$i++)) do echo "$lista[$i]" done
Esempi utili
Lavorano con gli script spesso abbiamo bisogno di leggere, spostare, cercare e convertire file ecc. Ecco un po' di esempi veloci
Operazioni sui file
#!/bin/bash file="prova.txt" if [ -e $file ]; #per l'opzione -e consulta la legenda then echo "File esiste" else echo "File non esiste" fi # -b filename Block special file # -c filename Special character file # -d directoryname Check for directory existence # -e filename Check for file existence # -f filename Check for regular file existence not a directory # -G filename Check if file exists and is owned by effective group ID. # -g filename true if file exists and is set-group-id. # -k filename Sticky bit # -L filename Symbolic link # -O filename True if file exists and is owned by the effective user id. # -r filename Check if file is a readable # -S filename Check if file is socket # -s filename Check if file is nonzero size # -u filename Check if file set-ser-id bit is set # -w filename Check if file is writable # -x filename Check if file is executable
Un loop utile
#!/bin/bash # cicla tutti i file in una cartella for f in $( ls ~/Scrivania ); do echo $f done
Uno script che rinomina file (sintassi avanzata)
#!/bin/bash # Questo script cerca nei nomi dei file e sostiuisce tutti gli spazi con "_" # la cartella da cercare, cartella="~/musica" # Il simbolo pipe "|" redirige lo STDOUT (standard output) nello STDIN (standard input) di un altro # il programma "find" serve per cercare "-type f" cerca solo file find $cartella -type f | while read file; do # [:space:] è usato nelle espressioni regolari per indicare lo spazio if [[ "$file" = *[[:space:]]* ]]; then # in un unico colpo rinomina il file usando "echo $file | tr ' ' '_'" come seconda opzione di "mv" # praticamente stampa il nome del file modificato tramite "tr" è un programma che manipola stringhe mv "$file" `echo $file | tr ' ' '_'` fi; # fine del loop done
Uno script di Conversione da .doc(x) a .pdf dato un elenco di ricerca
In un file .csv abbiamo su ogni riga il nome di un file .doc da convertire in .pdf
#!/bin/bash #cartella di ricerca ricerca="~/documenti" #il file con l'elenco file_ricerca="~/elenco.csv" #una cartella per salvare i file salvati cartella_salvataggio="~/salvataggio_pdf" #controllo se la cartella di salvataggio esiste altrimenti ne creo una if [ -d $cartella_salvataggio ]; then echo "La cartella esiste" else mkdir cartella_salvataggio fi #mi sposto nella cartella di ricerca, altrimenti find cerca a partire dalla posizione dove si trova lo script cd ricerca #ogni ciclo inserisce una linea del file di ricerca nella variabile "linea", vedi chiusura per la lettura while read linea; do #"find"il comando che cerca, -iname è l'opzione che non distingue tra maiscole e minuscole # la forma "variabile=$(comando)" permette di salvare l'out di un comando in una variabile file_doc=$(find -iname $linea -type f) #controllo se la ricerca è vuota altrimenti converto, nel ciclo if metto la variabile tra "", se ci stanno spazi nel nome può generare errori strani if [ "$file_doc" == ""]; then echo "Il file $linea non si trova in questa cartella" else # copio il file trovato nella cartella di salvataggio cp "$file_doc" "$cartella_salvataggio/$file_doc" # il programma unoconv di solito non è installato con la suite openoffice, in caso bisogna installarlo # su i sistemi Debian "sudo apt-get install unoconv" per installarlo unoconv -f pdf "$cartella_salvataggio/$file_doc" #cancello il file doc originale nella cartella di salvataggio che ormai non serve più rm "$cartella_salvataggio/$file_doc" fi # faccio leggere il file di ricerca a while done < $file_ricerca #mi sposto ad un livello superiore della cartella di salvataggio cd $cartella_salvataggio cd .. #comprimo tutto in un archivio tar -zcvf file_convertiti.tar.gz $cartella_salvataggio
Conclusioni
Per chi è proprio all'assciutto, per eseguire uno script basta spostarsi nella cartella dove si trova con "cd", e successivamente scrivendo il nome dello script preceduto da "./" (significa che si intende far partire un programma dalla posizione corrente):
cd ~/cartella_dove/si_trova/lo_script ./nome_script.sh
Di sicuro questa non è una guida esaustiva sul grande universo dello scripting shell, spero che sia almeno utile per superare il primo scoglio: riuscire a capire come iniziare.
Per il resto c'è google, sa tutto... :)
Ciao