Guida avanzata di scripting Bash

Un'approfondita esplorazione dell'arte dello scripting di shell

Mendel Cooper

4.1.05

19 novembre 2006

Diario delle Revisioni
Revisione 3.915 maggio 2006Revisionato da: mc
'SPICEBERRY' release: aggiornamento secondario.
Revisione 4.018 giugno 2006Revisionato da: mc
'WINTERBERRY' release: aggiornamento importante.
Revisione 4.108 ottobre 2006Revisionato da: mc
'WAXBERRY' release: aggiornamento secondario.

Questo manuale, per la cui comprensione non è necessaria una precedente conoscenza di scripting o di programmazione, permette di raggiungere rapidamente un livello di apprendimento intermedio/avanzato . . . tempo che tranquillamente ed inconsapevolmente si trasforma in piccoli frammenti di conoscenza e saggezza UNIX®. Può essere utilizzato come libro di testo, come manuale per l'autoapprendimento e come guida di riferimento per le tecniche di scripting di shell. Gli esercizi e gli esempi ampiamente commentati coinvolgono il lettore interessato, con l'avvertenza che per imparare veramente lo scripting, l'unico modo è quello di scrivere script.

Questo libro è adatto per l'insegnamento scolastico, come introduzione generale ai concetti della programmazione.

L'ultimo aggiornamento di questo documento, in forma di archivio compresso bzip2 "tarball" comprendente sia i sorgenti SGML che il formato HTML, può essere scaricato dal sito dell'autore. È anche disponibile una versione pdf in lingua originale. Vedi il change log per la cronologia delle revisioni.

Per la versione in lingua italiana è possibile reperirne una copia presso il PLUTO, ovvero il sito italiano collegato a tldp.


Dedica

Per Anita, fonte di ogni magia

Sommario
Part 1. Introduzione
1. Perché programmare la shell?
2. Iniziare con #!
2.1. Eseguire uno script
2.2. Esercizi preliminari
Part 2. I fondamenti
3. Caratteri speciali
4. Introduzione alle variabili ed ai parametri
4.1. Sostituzione di variabile
4.2. Assegnamento di variabile
4.3. Le variabili Bash non sono tipizzate
4.4. Tipi speciali di variabili
5. Quoting
5.1. Quoting di variabili
5.2. Escaping
6. Exit ed exit status
7. Verifiche
7.1. Costrutti condizionali
7.2. Operatori di verifica di file
7.3. Altri operatori di confronto
7.4. Costrutti condizionali if/then annidati
7.5. Test sulla conoscenza delle verifiche
8. Operazioni ed argomenti correlati
8.1. Operatori
8.2. Costanti numeriche
Part 3. Oltre i fondamenti
9. Variabili riviste
9.1. Variabili interne
9.2. Manipolazione di stringhe
9.3. Sostituzione di parametro
9.4. Tipizzare le variabili: declare o typeset
9.5. Referenziazione indiretta delle variabili
9.6. $RANDOM: genera un intero casuale
9.7. Il costrutto doppie parentesi
10. Cicli ed alternative
10.1. Cicli
10.2. Cicli annidati
10.3. Controllo del ciclo
10.4. Verifiche ed alternative
11. Sostituzione di comando
12. Espansione aritmetica
13. Ricreazione
Part 4. Comandi
14. Comandi interni e builtin
14.1. Comandi di controllo dei job
15. Filtri, programmi e comandi esterni
15.1. Comandi fondamentali
15.2. Comandi complessi
15.3. Comandi per ora/data
15.4. Comandi per l'elaborazione del testo
15.5. Comandi inerenti ai file e all'archiviazione
15.6. Comandi per comunicazioni
15.7. Comandi per il controllo del terminale
15.8. Comandi per le operazioni matematiche
15.9. Comandi diversi
16. Comandi di sistema e d'amministrazione
16.1. Analisi di uno script di sistema
Part 5. Argomenti avanzati
17. Espressioni Regolari
17.1. Una breve introduzione alle Espressioni Regolari
17.2. Globbing
18. Here document
18.1. Here String
19. Redirezione I/O
19.1. Uso di exec
19.2. Redirigere blocchi di codice
19.3. Applicazioni
20. Subshell
21. Shell con funzionalità limitate.
22. Sostituzione di processo
23. Funzioni
23.1. Funzioni complesse e complessità delle funzioni
23.2. Variabili locali
23.3. Ricorsività senza variabili locali
24. Alias
25. Costrutti lista
26. Array
27. /dev e /proc
27.1. /dev
27.2. /proc
28. Zero e Null
29. Debugging
30. Opzioni
31. Precauzioni
32. Stile dello scripting
32.1. Regole di stile non ufficiali per lo scripting di shell
33. Miscellanea
33.1. Shell e script interattivi e non
33.2. Shell wrapper
33.3. Verifiche e confronti: alternative
33.4. Ricorsività
33.5. "Colorare" con gli script
33.6. Ottimizzazioni
33.7. Argomenti vari
33.8. Sicurezza
33.9. Portabilità
33.10. Lo scripting di shell in Windows
34. Bash, versioni 2 e 3
34.1. Bash, versione 2
34.2. Bash, versione 3
35. Note conclusive
35.1. Nota dell'autore
35.2. A proposito dell'autore
35.3. Nota del traduttore
35.4. Dove cercare aiuto
35.5. Strumenti utilizzati per la produzione del libro
35.5.1. Hardware
35.5.2. Software e Printware
35.6. Ringraziamenti
Bibliografia
A. Script aggiuntivi
B. Tabelle di riferimento
C. Una breve introduzione a Sed e Awk
C.1. Sed
C.2. Awk
D. Codici di Exit con significati speciali
E. Una dettagliata introduzione all'I/O e alla redirezione I/O
F. Opzioni da riga di comando
F.1. Opzioni standard da riga di comando
F.2. Opzioni Bash da riga di comando
G. File importanti
H. Importanti directory di sistema
I. Localizzazione
J. Cronologia dei comandi
K. Un esempio di file .bashrc
L. Conversione dei file batch di DOS in script di shell
M. Esercizi
M.1. Analisi di script
M.2. Scrivere script
N. Cronologia delle revisioni
O. Siti per il download
P. Ancora da fare
Q. Copyright [1]
Lista delle Tabelle
14-1. Identificatori di job
30-1. Opzioni bash
33-1. Numeri che rappresentano i colori nelle sequenze di escape
B-1. Variabili speciali di shell
B-2. Operatori di verifica: confronti binari
B-3. Operatori di verifica: file
B-4. Sostituzione ed espansione di parametro
B-5. Operazioni su stringhe
B-6. Costrutti vari
C-1. Operatori sed di base
C-2. Esempi di operatori sed
D-1. Codici di Exit riservati
L-1. Parole chiave / variabili / operatori dei file batch e loro equivalenti di shell
L-2. Comandi DOS e loro equivalenti UNIX
N-1. Cronologia delle revisioni
Lista degli Esempi
2-1. cleanup: Uno script per cancellare i file di log in /var/log
2-2. cleanup: Lo script clean-up migliorato
2-3. cleanup: Una versione avanzata e generalizzata degli script precedenti.
3-1. Blocchi di codice e redirezione I/O
3-2. Salvare i risultati di un blocco di codice in un file
3-3. Eseguire un ciclo in background
3-4. Backup di tutti i file modificati il giorno precedente
4-1. Assegnamento e sostituzione di variabile
4-2. Assegnamento esplicito di variabile
4-3. Assegnamento di variabile, esplicito e indiretto
4-4. Intero o stringa?
4-5. Parametri posizionali
4-6. verifica del nome di dominio: wh, whois
4-7. Uso di shift
5-1. Visualizzare strane variabili
5-2. Sequenze di escape
6-1. exit / exit status
6-2. Negare una condizione utilizzando !
7-1. Cos'è vero?
7-2. Equivalenza di test, /usr/bin/test, [ ] e /usr/bin/[
7-3. Verifiche aritmetiche utilizzando (( ))
7-4. Ricerca di link interrotti (broken link)
7-5. Confronti numerici e di stringhe
7-6. Verificare se una stringa è nulla
7-7. zmore
8-1. Massimo comun divisore
8-2. Utilizzo delle operazioni aritmetiche
8-3. Condizioni di verifica composte utilizzando && e ||
8-4. Rappresentazione di costanti numeriche
9-1. $IFS e gli spazi
9-2. Input temporizzato
9-3. Input temporizzato, un ulteriore esempio
9-4. read temporizzato
9-5. Sono root?
9-6. arglist: Elenco degli argomenti con $* e $@
9-7. Comportamento incoerente di $* e $@
9-8. $* e $@ quando $IFS è vuota
9-9. Variabile underscore
9-10. Inserire una riga vuota tra i paragrafi di un file di testo
9-11. Conversione di formato di file grafici e modifica del nome dei file
9-12. Conversione di file in audio streaming nel formato ogg
9-13. Emulare getopt
9-14. Modi alternativi di estrarre sottostringhe
9-15. Sostituzione di parametro e messaggi d'errore
9-16. Sostituzione di parametro e messaggi "utilizzo"
9-17. Lunghezza di una variabile
9-18. Ricerca di corrispondenza nella sostituzione di parametro
9-19. Rinominare le estensioni dei file:
9-20. Utilizzare la verifica di occorrenza per controllare stringhe arbitrarie
9-21. Verifica di occorrenza di prefissi o suffissi di stringa
9-22. Utilizzare declare per tipizzare le variabili
9-23. Referenziazioni indirette
9-24. Passare una referenziazione indiretta a awk
9-25. Generare numeri casuali
9-26. Scegliere una carta a caso dal mazzo
9-27. Numero casuale in un intervallo dato
9-28. Lanciare un dado con RANDOM
9-29. Cambiare il seme di RANDOM
9-30. Numeri pseudocasuali utilizzando awk
9-31. Gestire le variabili in stile C
10-1. Semplici cicli for
10-2. Ciclo for con due parametri in ogni elemento [lista]
10-3. Fileinfo: operare su un elenco di file contenuto in una variabile
10-4. Agire sui file con un ciclo for
10-5. Tralasciare in [lista] in un ciclo for
10-6. Generare [lista] in un ciclo for con la sostituzione di comando
10-7. Un'alternativa con grep per i file binari
10-8. Elencare tutti gli utenti del sistema
10-9. Verificare tutti i file binari di una directory in cerca degli autori
10-10. Elencare i link simbolici presenti in una directory
10-11. Link simbolici presenti in una directory salvati in un file
10-12. Un ciclo for in stile C
10-13. Utilizzare efax in modalità batch
10-14. Un semplice ciclo while
10-15. Un altro ciclo while
10-16. Ciclo while con condizioni multiple
10-17. Sintassi in stile C di un ciclo while
10-18. Ciclo until
10-19. Cicli annidati
10-20. Effetti di break e continue in un ciclo
10-21. Interrompere un ciclo ad un determinato livello
10-22. Proseguire ad un livello di ciclo superiore
10-23. Uso di continue N in un caso reale
10-24. Impiego di case
10-25. Creare menu utilizzando case
10-26. Usare la sostituzione di comando per creare la variabile di case
10-27. Una semplice ricerca di stringa
10-28. Verificare un input alfabetico
10-29. Creare menu utilizzando select
10-30. Creare menu utilizzando select in una funzione
11-1. Stupid script tricks
11-2. Generare una variabile da un ciclo
11-3. Trovare anagrammi
14-1. Uno script che genera istanze multiple di sé stesso
14-2. printf in azione
14-3. Assegnamento di variabile utilizzando read
14-4. Cosa succede quando a read non è associata una variabile
14-5. Input su più righe per read
14-6. Rilevare i tasti freccia
14-7. Utilizzare read con la redirezione di file
14-8. Problemi leggendo da una pipe
14-9. Cambiare la directory di lavoro corrente
14-10. Facciamo fare a let qualche calcolo aritmetico.
14-11. Dimostrazione degli effetti di eval
14-12. Forzare un log-off
14-13. Una versione di rot13
14-14. Utilizzare eval per forzare una sostituzione di variabile in uno script Perl
14-15. Utilizzare set con i parametri posizionali
14-16. Invertire i parametri posizionali
14-17. Riassegnare i parametri posizionali
14-18. "Annullare" una variabile
14-19. Utilizzare export per passare una variabile ad uno script awk incorporato
14-20. Utilizzare getopts per leggere le opzioni/argomenti passati ad uno script
14-21. "Includere" un file dati
14-22. Un (inutile) script che "carica" se stesso
14-23. Effetti di exec
14-24. Uno script che esegue se stesso con exec
14-25. Attendere la fine di un processo prima di continuare
14-26. Uno script che uccide sé stesso
15-1. Utilizzare ls per creare un sommario da salvare in un CDR
15-2. Ciao o arrivederci
15-3. Badname, elimina, nella directory corrente, i file i cui nomi contengono caratteri inappropriati e spazi.
15-4. Cancellare un file tramite il suo numero di inode
15-5. Creare un file di log utilizzando xargs per verificare i log di sistema
15-6. Copiare i file della directory corrente in un'altra
15-7. Terminare un processo usando il suo nome
15-8. Analisi di frequenza delle parole utilizzando xargs
15-9. Utilizzo di expr
15-10. Utilizzo di date
15-11. Analisi di frequenza delle parole
15-12. Quali file sono degli script?
15-13. Generare numeri casuali di 10 cifre
15-14. Utilizzare tail per controllare il log di sistema
15-15. Simulare grep in uno script
15-16. Cercare una definizione nel Webster's Dictionary ed. 1913
15-17. Verificare la validità delle parole con un dizionario
15-18. toupper: Trasforma tutte le lettere di un file in maiuscole
15-19. lowercase: Cambia in lettere minuscole tutti i nomi dei file della directory corrente
15-20. du: Conversione di file di testo DOS al formato UNIX
15-21. rot13: cifratura ultra debole
15-22. Generare "Rompicapi Cifrati" di frasi celebri
15-23. Dimensionare un elenco di file
15-24. Utilizzo di column per impaginare un elenco di directory
15-25. nl: Uno script che numera le proprie righe
15-26. manview: visualizzazione formattata di pagine di manuale
15-27. Utilizzo di cpio per spostare una directory
15-28. Decomprimere un archivio rpm
15-29. Togliere i commenti da sorgenti C
15-30. Esplorare /usr/X11R6/bin
15-31. Un comando strings "migliorato"
15-32. Utilizzare cmp in uno script per confrontare due file
15-33. basename e dirname
15-34. Verificare l'integrità dei file
15-35. Decodificare file
15-36. Scoprire dove effettuare una segnalazione di uno spammer
15-37. Analisi di un dominio di spam
15-38. Ottenere una quotazione di borsa
15-39. Aggiornare FC4
15-40. Uso di ssh
15-41. Uno script che si auto-invia
15-42. Rata mensile di un mutuo
15-43. Conversione di base
15-44. Invocare bc usando un here document
15-45. Calcolo del pi greco
15-46. Convertire un numero decimale in esadecimale
15-47. Fattorizzazione
15-48. Calcolo dell'ipotenusa di un triangolo
15-49. Utilizzo di seq per generare gli argomenti di un ciclo
15-50. Conta lettere
15-51. Utilizzo di getopt per analizzare le opzioni passate da riga di comando
15-52. Uno script che copia sè stesso
15-53. Esercitarsi con dd
15-54. Intercettare i tasti premuti
15-55. Cancellare in modo sicuro un file
15-56. Generatore di nomi di file
15-57. Convertire i metri in miglia
15-58. Utilizzo di m4
16-1. Impostare una nuova password
16-2. Abilitare un carattere di cancellazione
16-3. Password segreta: disabilitare la visualizzazione a terminale
16-4. Rilevamento dei tasti premuti
16-5. Verificare se su un server remoto è in esecuzione identd
16-6. pidof aiuta ad terminare un processo
16-7. Verificare un'immagine CD
16-8. Creare un filesystem in un file
16-9. Aggiungere un nuovo hard disk
16-10. Usare umask per celare l'output di un file da occhi indagatori
16-11. killall, da /etc/rc.d/init.d
18-1. broadcast: invia un messaggio a tutti gli utenti connessi
18-2. File di prova: crea un file di prova di due righe
18-3. Messaggio di più righe usando cat
18-4. Messaggio di più righe con cancellazione dei caratteri di tabulazione
18-5. Here document con sostituzione di parametro
18-6. Caricare due file nella directory incoming di Sunsite
18-7. Sostituzione di parametro disabilitata
18-8. Uno script che genera un altro script
18-9. Here document e funzioni
18-10. Here document "anonimo"
18-11. Commentare un blocco di codice
18-12. Uno script che si auto-documenta
18-13. Anteporre una riga in un file
18-14. Analizzare un file mailbox
19-1. Redirigere lo stdin usando exec
19-2. Redirigere lo stdout utilizzando exec
19-3. Redirigere con exec, nello stesso script, sia lostdin che lo stdout
19-4. Evitare una subshell
19-5. Ciclo while rediretto
19-6. Una forma alternativa di ciclo while rediretto
19-7. Ciclo until rediretto
19-8. Ciclo for rediretto
19-9. Ciclo for rediretto (rediretti sia lo stdin che lo stdout)
19-10. Costrutto if/then rediretto
19-11. File dati nomi.data usato negli esempi precedenti
19-12. Eventi da registrare in un file di log
20-1. Ambito di una variabile in una subshell
20-2. Elenco dei profili utente
20-3. Eseguire processi paralleli tramite le subshell
21-1. Eseguire uno script in modalità ristretta
23-1. Semplici funzioni
23-2. Funzione con parametri
23-3. Funzioni e argomenti passati allo script da riga di comando
23-4. Passare una referenziazione indiretta a una funzione
23-5. Dereferenziare un parametro passato a una funzione
23-6. Ancora, dereferenziare un parametro passato a una funzione
23-7. Il maggiore di due numeri
23-8. Convertire i numeri arabi in numeri romani
23-9. Verificare valori di ritorno di grandi dimensioni in una funzione
23-10. Confronto di due interi di grandi dimensioni
23-11. Il vero nome dal nome utente
23-12. Visibilità di una variabile locale
23-13. Ricorsività per mezzo di una variabile locale
23-14. La torre di Hanoi
24-1. Alias in uno script
24-2. unalias: abilitare e disabilitare un alias
25-1. Usare una lista and per verificare gli argomenti da riga di comando
25-2. Un'altra verifica di argomenti da riga di comando utilizzando una lista and
25-3. Utilizzare la lista or in combinazione con una lista and
26-1. Un semplice uso di array
26-2. Impaginare una poesia
26-3. Operazioni diverse sugli array
26-4. Operazioni sulle stringhe negli array
26-5. Inserire il contenuto di uno script in un array
26-6. Alcune proprietà particolari degli array
26-7. Array vuoti ed elementi vuoti
26-8. Inizializzare gli array
26-9. Copiare e concatenare array
26-10. Ancora sul concatenamento di array
26-11. Una vecchia conoscenza: il Bubble Sort
26-12. Array annidati e referenziazioni indirette
26-13. Applicazione complessa di array: Crivello di Eratostene
26-14. Simulare uno stack push-down
26-15. Applicazione complessa di array: Esplorare strane serie matematiche
26-16. Simulazione di un array bidimensionale, con suo successivo rovesciamento
27-1. Uso di /dev/tcp per la verifica di una connessione
27-2. Trovare il processo associato al PID
27-3. Stato di una connessione
28-1. Evitare i cookie
28-2. Impostare un file di swap usando /dev/zero
28-3. Creare un ramdisk
29-1. Uno script errato
29-2. Parola chiave mancante
29-3. test24: un altro script errato
29-4. Verificare una condizione con una funzione con assert
29-5. Trap di exit
29-6. Pulizia dopo un Control-C
29-7. Tracciare una variabile
29-8. Esecuzione di processi multipli (su una postazione SMP)
31-1. I confronti numerici e quelli di stringhe non si equivalgono
31-2. I trabocchetti di una subshell
31-3. Concatenare con una pipe l'output di echo a read
33-1. Shell wrapper
33-2. Uno shell wrapper leggermente più complesso
33-3. Uno shell wrapper generico che effettua una registrazione in un file di log
33-4. Uno shell wrapper per uno script awk
33-5. Uno shell wrapper per un altro script awk
33-6. Perl inserito in uno script Bash
33-7. Script Bash e Perl combinati
33-8. Un (inutile) script che richiama sé stesso ricorsivamente
33-9. Un (utile) script che richiama sé stesso ricorsivamente
33-10. Un altro (utile) script che richiama sé stesso ricorsivamente
33-11. Una rubrica di indirizzi "a colori"
33-12. Disegnare un rettangolo
33-13. Visualizzare testo colorato
33-14. Una gara "ippica"
33-15. Uno stratagemma per il valore di ritorno
33-16. Uno stratagemma per valori di ritorno multipli
33-17. Passaggio e restituzione di array
33-18. Divertirsi con gli anagrammi
33-19. Widget invocati da uno script di shell
34-1. Espansione di stringa
34-2. Referenziazioni indirette a variabili - una forma nuova
34-3. Applicazione di un semplice database, con l'utilizzo della referenziazione indiretta
34-4. Utilizzo degli array e di vari altri espedienti per simulare la distribuzione casuale di un mazzo di carte a 4 giocatori
A-1. mailformat: impaginare un messaggio e-mail
A-2. rn: una semplice utility per rinominare un file
A-3. blank-rename: rinomina file i cui nomi contengono spazi
A-4. encryptedpw: upload a un sito ftp utilizzando una password criptata localmente
A-5. copy-cd: copiare un CD di dati
A-6. Serie di Collatz
A-7. days-between: calcolo del numero di giorni intercorrenti tra due date
A-8. Creare un "dizionario"
A-9. Codifica soundex
A-10. "Game of Life"
A-11. File dati per "Game of Life"
A-12. behead: togliere le intestazioni dai messaggi di e-mail e di news
A-13. ftpget: scaricare file via ftp
A-14. password: generare password casuali di 8 caratteri
A-15. fifo: eseguire backup giornalieri utilizzando le named pipe
A-16. Generare numeri primi utilizzando l'operatore modulo
A-17. tree: visualizzare l'albero di una directory
A-18. string functions: funzioni per stringhe simili a quelle del C
A-19. Informazioni sulle directory
A-20. Database object-oriented
A-21. Libreria di funzioni hash
A-22. Colorare del testo con le funzioni di hash
A-23. Altro sulle funzioni di hash
A-24. Montare le chiavi di memoria USB
A-25. Preservare i weblog
A-26. Proteggere le stringhe letterali
A-27. Stringhe letterali non protette
A-28. Identificare uno spammer
A-29. Caccia allo spammer
A-30. Rendere wget più semplice da usare
A-31. Uno script per il "podcasting"
A-32. Backup notturno su un HD firewire
A-33. Il comando cd esteso
A-34. Fondamenti rivisitati
C-1. Conteggio delle occorrenze di lettere
K-1. Esempio di file .bashrc
L-1. VIEWDATA.BAT: file batch DOS
L-2. viewdata.sh: Script di shell risultante dalla conversione di VIEWDATA.BAT
P-1. Visualizzare l'ambiente di un server