Bash scripting: differenze tra le versioni

sostituito echo con printf, più modifiche minori, ma resta da dividere in più guide
m (→‎Espansione di percorso: tag non chiuso)
(sostituito echo con printf, più modifiche minori, ma resta da dividere in più guide)
Riga 1: Riga 1:
{{Versioni_compatibili}}
{{Versioni_compatibili}}
=Introduzione=
=Introduzione=
Questa non è una guida completa, per la vastità dell'argomento trattato, e allo stato attuale non è indicata nemmeno come prima guida a chi voglia approcciarsi a Bash.
Questa non è una guida completa, per la vastità dell'argomento trattato, e per il momento non è indicata nemmeno come prima guida a chi voglia approcciarsi a Bash.


Infatti è data per scontata la conoscenza dei comandi:
Infatti allo stato attuale è necessaria almeno la conoscenza dei comandi:
* di input e output (<code>read</code>, <code>echo</code>/<code>printf</code>);
* di condizione (<code>test/[</code>);
* di condizione (<code>test/[</code>, <code>[[</code>);
* di esecuzione condizionata (<code>if</code>);
* di esecuzione condizionata (<code>if</code>, <code>case</code>);
* di ciclo (<code>for</code>).
* di ciclo (<code>for</code>, <code>while</code>);
 
* di cambio directory e permessi dei file creati (<code>cd</code>, <code>umask</code>);
Mentre non sono trattati altri comandi importanti:
* per definire funzioni (<code>... ()</code>);
* di input (<code>read</code>);
* di condizione avanzata (<code>[[</code>, <code>((</code>);
* di esecuzione condizionata (<code>case</code>);
* di ciclo (<code>while</code>);
* per definire funzioni (<code>... ()</code> / <code>function ...</code>);
* per effettuare il parsing degli argomenti (<code>getopts</code>);
* per effettuare il parsing degli argomenti (<code>getopts</code>);
* modificatori di variabili (<code>readonly</code>, <code>local</code>, <code>declare</code>);
* modificatori di variabili (<code>readonly</code>, <code>local</code>, <code>declare</code>);
* ecc...
* ecc...


Lo scopo della guida è invece, per chi abbia già appreso i concetti più basilari, quello di evidenziare i comportamenti più distintivi e facili da sbagliare di Bash, con enfasi particolare sulle espansioni di stringhe, estremamente diverse da altri linguaggi di programmazione. Così da passare poi a guide più avanzate per completare l'apprendimento dello scripting in Bash.
Al momento lo scopo della guida è invece, per chi abbia già appreso i concetti più basilari, di evidenziare i comportamenti più distintivi e facili da sbagliare di Bash, con enfasi particolare sulle espansioni di stringhe, estremamente diverse da altri linguaggi di programmazione. Così da passare poi a guide più avanzate per completare l'apprendimento dello scripting in Bash.


Per l'uso interattivo della shell si rimanda a [[Bash tips]]. Si noti che l'espansione della history, che qui non è trattata, è attiva soltanto in modalità interattiva.
Per l'uso interattivo della shell si rimanda a [[Bash tips]]. Si noti che l'espansione della history, che qui non è trattata, è attiva soltanto in modalità interattiva.
==Comandi di output: echo e printf==
Il comando <code>echo</code> è largamente diffuso in Bash per stampare delle stringhe su schermo, perché ha una sintassi più semplice di <code>printf</code> e non risente delle stesse limitazioni della shell POSIX, che interpreta ed espande i caratteri di escape (si legga la sezione dedicata) senza che ci sia un modo di stampare letteralmente una stringa.
Tuttavia negli script l'uso di <code>echo</code> non è sempre possibile, rendendo necessaria la conoscenza almeno basilare di <code>printf</code>. In particolare, se si vuole stampare il contenuto di $var, '''non''' è sempre corretto scrivere:
<pre>
echo -n "$var" # stampa senza a capo finale
echo "$var"    # stampa con a capo finale
</pre>
perché $var potrebbe iniziare con il carattere <code>-</code> ed essere una combinazione delle opzioni: -e, -E, -n.
Con <code>echo</code> non esiste un modo che assicuri la stampa del contenuto di una variabile in ogni situazione possibile. E non sempre il contenuto è noto a priori: in presenza di espansioni, come vedremo poi, o di input dell'utente. Per non incorrere in errori difficili da riconoscere, <code>echo</code> andrebbe usato soltanto nella shell interattiva, dove l'uso è più comodo, e <code>printf</code> andrebbe preferito anche in Bash per gli script, perché più robusto.
In questa guida d'ora in poi si farà riferimento soltanto a <code>printf</code>.
===Uso di printf===
Sintassi base:
<pre>printf formato [ "stringa" ]</pre>
Gli usi più avanzati non sono trattati in questa guida.
Stampa senza a capo finale:
<pre>printf %s "$var"</pre>
Caratteri speciali (senza %s non serve una stringa):
<pre>
printf \\n  # nuova riga
printf \\t  # tabulazione
printf \\r  # ritorno a inizio riga
printf \\888 # stampa il carattere ascii con codice in base 8
</pre>
Stampa con a capo finale:
<pre>printf %s\\n "$var"</pre>
Stampa con a capo prima e dopo:
<pre>printf \\n%s\\n "$var" </pre>
Per usi più complessi, anziché rendere più complicato il formato, è preferibile utilizzare più comandi <code>printf</code>:
<pre>
# funziona, ma è poco chiaro per chi non ne conosce la sintassi
printf '%s\n\t%s  %s\n' "Sintassi:" "$0" "[ arg ]" # più stringhe
# equivalente, ma più leggibile:
printf %s\\n    "Sintassi:"
printf \\t%s\\n "$0  [ arg ]"
</pre>


=Variabili (stringhe)=
=Variabili (stringhe)=
Riga 40: Riga 90:
</pre>
</pre>


==Espansione==
==Espansione di variabile==
Con l'unica eccezione dell'assegnazione, quando si accede al contenuto di una variabile senza quotarla, questa può essere trasformata in più di una singola stringa ('''esplosione''') in base agli spazi (e tabulazioni e "a capo") contenuti, e perfino in "niente" se è vuota. "Niente" proprio come se non presente nel codice.
Con l'unica eccezione dell'assegnazione, quando si accede al contenuto di una variabile senza quotarla, questa può essere trasformata in più di una singola stringa ('''esplosione''') in base agli spazi (e tabulazioni e "a capo") contenuti, e perfino in "niente" se è vuota. "Niente" proprio come se non presente nel codice.


Riga 63: Riga 113:
L'opzione deve essere supportata dal comando esterno, non è trattata specialmente dalla shell.}}
L'opzione deve essere supportata dal comando esterno, non è trattata specialmente dalla shell.}}


D'altra parte accedere una variabile senza quotarla permette di assegnare alla variabile tutte le opzioni da passare a un comando, se sono stringhe senza spazi e caratteri speciali, per poi accederle in una volta sola:
D'altra parte accedere una variabile senza quotarla permette di assegnare alla variabile tutte le opzioni da passare a un comando, se sono stringhe senza spazi e caratteri speciali che potrebbero essere espansi nuovamente (<code>* ? [ ]</code>), per poi accederle in una volta sola:


<pre>ARGUMENTS="--arg1 --arg2 ..."
<pre>ARGUMENTS="--arg1 --arg2 ..."
Riga 86: Riga 136:
<pre>
<pre>
for file in "$@"; do
for file in "$@"; do
     # Fare quello che si vuole con $file
     # fare quello che si vuole con "$file"
    echo "$file"
     # ...
     # ...
done
done
Riga 115: Riga 164:
Per esempio:
Per esempio:
<pre>
<pre>
echo parola1; parola2      # ERRORE: parola2 è considerata un altro comando!
printf %s\\n parola1; parola2      # ERRORE: parola2 è considerata un altro comando!
echo "parola1; parola2"    # corretto
printf %s\\n "parola1; parola2"    # corretto
echo parola1    parola2  # stampa parola1 parola2 (senza caratteri speciali) con un singolo spazio
printf %s\\n parola1    parola2  # stampa parola1 parola2 (senza caratteri speciali) con un singolo spazio
echo "parola1    parola2" # stampa mantenendo gli spazi tra le due parole
printf %s\\n "parola1    parola2" # stampa mantenendo gli spazi tra le due parole
 
# con una variabile
# con una variabile
var="parola1    parola2" # assegno la stringa alla variabile
var="parola1    parola2"         # assegno la stringa alla variabile
echo $var                  # la stampo con un singolo spazio tra le parole
printf %s\\n $var                  # la stampo con un singolo spazio tra le parole
echo "$var"                # la stampo così com'è scritta
printf %s\\n "$var"                # la stampo così com'è scritta
</pre>
</pre>


Riga 128: Riga 178:
<pre>
<pre>
# stampa tutto su una riga
# stampa tutto su una riga
echo "testo su \
printf %s\\n "testo su \
più \
più \
righe"
righe"


# stampa su più righe
# stampa su più righe
echo "testo su
printf %s\\n "testo su
più
più
righe"
righe"
Riga 141: Riga 191:
Sintassi: <code>$'stringa'</code>
Sintassi: <code>$'stringa'</code>


Se l'espansione non è quotata o preceduta da escape, e la stringa non è una variabile, ne espande i caratteri di escape (utilizzabili anche con ''printf'' ed ''echo -e''):
Se l'espansione non è quotata o preceduta da escape, e la stringa non è una variabile, ne espande i caratteri di escape (utilizzabili anche con ''printf''):
* '''\n''', nuova riga;
* '''\n''', nuova riga;
* '''\b''', backspace (cancella un carattere);
* '''\b''', backspace (cancella un carattere);
Riga 151: Riga 201:
==Racchiudere tra apici==
==Racchiudere tra apici==
Con gli apici (apostrofi) si riducono i caratteri speciali a uno soltanto, lo stesso apice, rappresentando la stringa per il suo solo valore letterale e impedendo tutte le espansioni:
Con gli apici (apostrofi) si riducono i caratteri speciali a uno soltanto, lo stesso apice, rappresentando la stringa per il suo solo valore letterale e impedendo tutte le espansioni:
<pre>echo '$PATH "" \ `ls ..` \$HOME ~ * .[a-z]*'  # stampa la stringa tra apici, letteralmente</pre>
<pre>printf %s\\n '$PATH "" \ `ls ..` \$HOME ~ * .[a-z]*'  # stampa la stringa tra apici, letteralmente</pre>


Lo svantaggio è che non esiste un carattere di escape:
Lo svantaggio è che non esiste un carattere di escape:
<pre>echo 'L'\''albero di... ' # stampa "L'albero di..." (l'accento non può essere racchiuso tra apici)</pre>
<pre>printf %s\\n 'L'\''albero di... ' # stampa "L'albero di..." (l'accento non può essere racchiuso tra apici)</pre>


==Quotare (tra virgolette)==
==Quotare (tra virgolette)==
Racchiudere tra virgolette ogni stringa è raccomandabile, anche se non sempre necessario, così da ridurre il numero di caratteri speciali a cui pensare, permettendo allo stesso tempo l'espansione sicura delle variabili e dei comandi. I soli caratteri speciali rimasti sono <code>$</code>, <code>`</code> (ma non l'apice), <code>"</code> e <code>\</code>, che devono essere preceduti dal carattere di escape <code>\</code>. Le sole espansioni permesse all'interno di una stringa quotata sono quelle attivate da <code>$</code>, ossia di variabile/parametro, di comando e aritmetiche.
Racchiudere tra virgolette ogni stringa è raccomandabile, anche se non sempre necessario, così da ridurre il numero di caratteri speciali a cui pensare, permettendo allo stesso tempo l'espansione sicura delle variabili e dei comandi. I soli caratteri speciali rimasti sono <code>$</code>, <code>`</code> (ma non l'apice), <code>"</code> e <code>\</code>, che devono essere preceduti dal carattere di escape <code>\</code>.
 
All'interno di una stringa quotata l'espansione <code>$'stringa'</code> e tutte quelle che '''non''' sono attivabili da <code>$</code> non sono permesse. Sono possibili soltanto le espansioni di variabile/parametro, di comando e aritmetiche.


Per esempio:
Per esempio:
<pre>
<pre>
echo "$PATH"      # espande la variabile PATH e ne stampa il contenuto
printf %s\\n "$PATH"      # espande la variabile PATH e ne stampa il contenuto
echo "\$HOME"      # stampa letteralmente $HOME, senza espanderla (è equivalente a '$HOME')
printf %s\\n "\$HOME"      # stampa letteralmente $HOME, senza espanderla (è equivalente a '$HOME')
echo "\"\" \\"    # è equivalente a '"" \'
printf %s\\n "\"\" \\"    # è equivalente a '"" \'
echo "$(ls ..)"    # Esegue il comando "ls .." e ne stampa l'output
printf %s\\n "$(ls ..)"    # Esegue il comando "ls .." e ne stampa l'output
echo "$((2*2))"    # Esegue l'espressione aritmetica e stampa 4
printf %s\\n "$((2*2))"    # Esegue l'espressione aritmetica e stampa 4
echo "~ * .[a-z]*" # non effettua le espansioni di tilda e percorso, ma stampa letteralmente
printf %s\\n "~ * .[a-z]*" # non effettua le espansioni di tilda e percorso, ma stampa letteralmente
echo "{a,b} $'\n'" # stampa letteralmente, senza espansioni
printf %s\\n "{a,b} $'\n'" # stampa letteralmente, senza espansioni
</pre>
</pre>


=Espansioni in stringhe quotate=
=Espansioni in stringhe quotate=
Le espansione attivate da <code>$</code> avvengono con la stessa priorità, e in una stringa quotata sono le uniche permesse, quindi il risultato di un'espansione non può essere espanso una seconda volta all'interno di una stringa quotata. Sono le espansioni di variabile, già vista, e quelle di parametro, di comando e aritmetica (intera).
Le espansione attivate da <code>$</code> avvengono con la stessa priorità, e in una stringa quotata con l'eccezione di <code>$'stringa'</code> sono le uniche permesse, quindi il risultato di un'espansione non può mai essere espanso un'altra volta all'interno di una stringa quotata. Sono permesse le sole espansioni di variabile, già vista, e di parametro, di comando e aritmetica (intera), che saranno trattate in seguito.


==Espansione di parametro (stringa)==
==Espansione di parametro (stringa)==
È una forma modificata dell'espansione di variabile, che permette di operare sulla stringa contenuta con un modificatore.
È una forma modificata dell'espansione di variabile, che permette di operare sulla stringa contenuta con un modificatore.


L'espansione di parametro è utilizzabile ogni volta che lo è quella di variabile, con un'unica differenza: l'espansione di variabile può essere contenuta in un'espansione di parametro, mentre non è possibile annidare più espansioni di parametro.
L'espansione di parametro è utilizzabile ogni volta che lo è quella di variabile, con un'unica differenza: l'espansione di variabile può essere contenuta in alcune espansioni di parametro, purché non al posto del nome della variabile, mentre non è mai possibile annidare più espansioni di parametro.


Modificatori:
Modificatori:
Riga 188: Riga 240:
<pre>
<pre>
var="stringa"
var="stringa"
puntatore="var"   # puntatore contiene il nome (senza $) di $var
rif="var"             # rif contiene il nome (senza $) di $var
var2=${!puntatore} # equivalente a: var2=$var
var2=${!rif}         # equivalente a: var2=$var
echo "$var2"       # stampa: stringa
printf %s\\n "$var2" # stampa: stringa
echo ${#var2}     # stampa: 7 (la lunghezza di "stringa")
printf %s\\n ${#var2} # stampa: 7 (la lunghezza di "stringa")
</pre>
</pre>


Riga 202: Riga 254:
<pre>
<pre>
VAR="stringa-di-esempio"
VAR="stringa-di-esempio"
echo "${VAR#stringa-}"
printf %s\\n "${VAR#stringa-}"
</pre>
</pre>
ritorna il contenuto della variable VAR senza il prefisso "stringa-". VAR non viene modificata, salvo una nuova assegnazione:
ritorna il contenuto della variable VAR senza il prefisso "stringa-". VAR non viene modificata, salvo una nuova assegnazione:
Riga 239: Riga 291:
VAR="questa.sarebbe.una.stringa.di.esempio"
VAR="questa.sarebbe.una.stringa.di.esempio"
    
    
                    # Risultato:
                            # Risultato:
    
    
echo "${VAR#*.}"    # --> sarebbe.una.stringa.di.esempio
printf %s\\n "${VAR#*.}"    # --> sarebbe.una.stringa.di.esempio
echo "${VAR##*.}"    # --> esempio
printf %s\\n "${VAR##*.}"    # --> esempio
    
    
echo "${VAR%.*}"    # --> questa.sarebbe.una.stringa.di
printf %s\\n "${VAR%.*}"    # --> questa.sarebbe.una.stringa.di
echo "${VAR%%.*}"    # --> questa
printf %s\\n "${VAR%%.*}"    # --> questa
    
    
echo "${VAR/st/ST}"  # --> queSTa.sarebbe.una.stringa.di.esempio
printf %s\\n "${VAR/st/ST}"  # --> queSTa.sarebbe.una.stringa.di.esempio
echo "${VAR//st/ST}" # --> queSTa.sarebbe.una.STringa.di.esempio
printf %s\\n "${VAR//st/ST}" # --> queSTa.sarebbe.una.STringa.di.esempio
</pre>
</pre>


Riga 255: Riga 307:
<pre>
<pre>
usage () {
usage () {
   echo "Usage: ${0##*/}"
   printf %s\\n "Usage: ${0##*/}"
}
}
</pre>
</pre>
Riga 272: Riga 324:
<pre>
<pre>
# assegna alla variabile $oggi la data in formato YYYY_MM_DD
# assegna alla variabile $oggi la data in formato YYYY_MM_DD
oggi=$(date +%F)  # senza virgolette
oggi=$(date '+%F')  # senza virgolette
oggi="$(date +%F)" # equivalente a sopra (non servono nelle assegnazioni)
oggi="$(date '+%F')" # equivalente a sopra (non servono nelle assegnazioni)


# associo a testo il contenuto del file indicato da $file
# associo a testo il contenuto del file indicato da $file
Riga 284: Riga 336:
<pre>
<pre>
# stampa stati
# stampa stati
echo "Login name: $(logname); Name: $(whoami); UID: $(id -ur); EUID: $(id -u); Groups: $(groups)"
printf %s\\n "Login name: $(logname); Name: $(whoami); UID: $(id -ur); EUID: $(id -u); Groups: $(groups)"
echo "OS: Debian GNU/Linux $(cat /etc/debian_version) ($(lsb_release -sc))" # uguale a $(lsb_release -sd)
printf %s\\n "OS: Debian GNU/Linux $(cat /etc/debian_version) ($(lsb_release -sc))" # uguale a $(lsb_release -sd)
echo "Kernel: $(uname) $(uname -r) ($(uname -v))"
printf %s\\n "Kernel: $(uname) $(uname -r) ($(uname -v))"
</pre>
</pre>


Riga 292: Riga 344:
Si noti che l'espansione di comando, come anche in '''sh''' (''POSIX''), non espande il comando a tutto l'output prodotto, ma omette sempre gli "a capo" finali. Se da una parte è utile nella maggior parte delle situazioni, può talvolta avere effetti collaterali difficili da prevedere. Si consideri per esempio:
Si noti che l'espansione di comando, come anche in '''sh''' (''POSIX''), non espande il comando a tutto l'output prodotto, ma omette sempre gli "a capo" finali. Se da una parte è utile nella maggior parte delle situazioni, può talvolta avere effetti collaterali difficili da prevedere. Si consideri per esempio:
<pre>
<pre>
echo ciao > file_prova # scrive ciao e un "a capo" nel file_prova
printf %s\\n ciao > ./file_prova # scrive ciao e un "a capo" nel file_prova
testo=$(cat file_prova) # associa il contenuto (SENZA "a capo") a $testo
testo=$(cat ./file_prova)       # associa il contenuto (SENZA "a capo") a $testo
echo "Bytes: ${#testo}" # NON è la dimensione esatta del file!
printf %s\\n "Bytes: ${#testo}" # NON è la dimensione esatta del file!
echo "$testo"           # stampa il contenuto di $testo (PIÙ un "a capo")
printf %s\\n "$testo" |          # invia la stringa a cmp (più un "a capo") per un confronto
echo "$testo" |        # invia la stringa a cmp per un confronto
   cmp - ./file_prova             # nessun errore!!!
   cmp - file_prova     # nessun errore!!!
printf %s\\n $?                 # infatti stampa 0
echo $?                 # infatti stampa 0
</pre>
</pre>


Riga 312: Riga 363:


# a titolo esemplicativo per l'espansione di comando
# a titolo esemplicativo per l'espansione di comando
nr=$(echo)         # SBAGLIATO, $nr è vuota
nr=$(printf \\n)   # SBAGLIATO, $nr è vuota
nr="$(echo)"      # SBAGLIATO, come sopra
nr="$(printf \\n)" # SBAGLIATO, $nr è sempre vuota
nr=$(printf "\n"# SBAGLIATO, $nr è sempre vuota


# una possibile soluzione...
# una possibile soluzione...
nr=$(printf "\nX") # $nr contiene "a capo" seguito da X
nr=$(printf \\nX) # $nr contiene "a capo" seguito da X
nr=${nr%X}        # $nr contiene "a capo" (la X è rimossa)
nr=${nr%X}        # $nr contiene "a capo" (la X è rimossa)


# Attenzione che il carattere aggiunto dev'essere nell'output del comando
# Attenzione che il carattere aggiunto dev'essere nell'output del comando
nr=$(printf "\n")X # SBAGLIATO, $nr contiene solo X
nr=$(printf \\n)X # SBAGLIATO, $nr contiene solo X
</pre>
</pre>


Riga 340: Riga 390:
altezza=5
altezza=5
area=$(($base * $altezza))
area=$(($base * $altezza))
echo "Area rettangolo: ${area}"      # Stampa 45
printf %s\\n "Area rettangolo: ${area}"      # Stampa 45
echo "Area triangolo: $(($area / 2))" # Stampa 22 (RICORDA: solo interi)
printf %s\\n "Area triangolo: $(($area / 2))" # Stampa 22 (RICORDA: solo interi)
</pre>
</pre>


=Espansioni non quotabili=
=Espansioni non quotabili=
Le seguenti espansioni avvengono unicamente in stringhe non quotate, almeno limitatamente ai caratteri speciali che le attivano. Con l'eccezione dell'espansione di tilda, l'unica che si espande sempre a una singola stringa, le espansioni non quotabili non sono utilizzabili direttamente in un'assegnazione.
Le espansioni trattate nelle sezioni successive avvengono unicamente in stringhe non quotate, almeno limitatamente ai caratteri speciali che le attivano. L'espansione <code>$'stringa'</code> non è quotabile, ma è stata già trattata con i caratteri di escape.
 
Le loro priorità sono tutte diverse: l'espansione di parentesi è quella maggiore, seguita dalla tilda, da tutte le espansioni attivabili con '''$''' (quelle quotabili e <code>$'stringa'</code>) e infine dall'espansione di percorso.


Le loro priorità sono tutte diverse: l'espansione di parentesi è quella maggiore, seguita dalla tilda, da tutte le espansioni quotabili e infine dall'espansione di percorso.
Inoltre le espansioni di parentesi e di percorso, che potrebbero essere espanse a più di una singola stringa, non sono possibili direttamente in un'assegnazione.


==Espansione di tilda==
==Espansione di tilda==
Riga 361: Riga 413:
Esempi:
Esempi:
<pre>
<pre>
var=~       # assegno la home dell'utente a $var
var=~               # assegno la home dell'utente a $var
var=$HOME   # equivalente (ma più chiaro)
var=$HOME           # equivalente (ma più chiaro)
var="~"     # assegno ~ a $var
var="~"             # assegno ~ a $var
echo "$var"  # stampo ~
printf %s\\n "$var"  # stampo ~
echo $var    # equivalente (nessuna espansione)
printf %s\\n $var    # equivalente (nessuna espansione)
var=~root   # assegno a var la home di root
var=~root           # assegno a var la home di root
echo ~      # stampo la home dell'utente
printf %s\\n ~      # stampo la home dell'utente
echo "$HOME" # equivalente
printf %s\\n "$HOME" # equivalente
echo "~"    # stampo ~
printf %s\\n "~"    # stampo ~
echo ~root  # stampo la home di root
printf %s\\n ~root  # stampo la home di root
echo ~fdsfd  # stampo ~fdsfd (l'utente fdsfd non esiste)
printf %s\\n ~fdsfd  # stampo ~fdsfd (l'utente fdsfd non esiste)
</pre>
</pre>


Riga 381: Riga 433:
L'espansione non è possibile, direttamente, in un'assegnazione. Avendo la priorità più bassa, contrariamente all'espansione di tilda può avvenire anche in seguito all'espansione di una variabile (e con ogni altra espansione), se non è quotata:
L'espansione non è possibile, direttamente, in un'assegnazione. Avendo la priorità più bassa, contrariamente all'espansione di tilda può avvenire anche in seguito all'espansione di una variabile (e con ogni altra espansione), se non è quotata:
<pre>
<pre>
var="./*"   # assegno ./* a $var
var="./*"           # assegno ./* a $var
var=./*     # come sopra (nessuna espansione in un'assegnazione)
var=./*             # come sopra (nessuna espansione in un'assegnazione)
echo "$var" # stampa letteralmente ./*
printf %s\\n "$var" # stampa letteralmente ./*
echo $var  # stampa la lista di tutti i file non nascosti
printf %s\\n $var  # stampa la lista di tutti i file non nascosti
            # nella directory corrente, oppure ./* se è vuota
                    # nella directory corrente, oppure ./* se è vuota
</pre>
</pre>


Riga 489: Riga 541:
Esempi:
Esempi:
<pre>
<pre>
comando &> /dev/null    # non stampa niente a schermo
comando &> /dev/null    # non stampa niente a schermo, neanche gli errori
comando > /dev/null 2>&1 # equivalente (POSIX)
comando > /dev/null 2>&1 # equivalente (POSIX)


Riga 501: Riga 553:
Infatti non esiste un modo di contenere il carattere ASCII n. 0 in nessuna posizione:
Infatti non esiste un modo di contenere il carattere ASCII n. 0 in nessuna posizione:
<pre>
<pre>
var=$(printf '\000')    # SBAGLIATO: $var è vuota
var=$(printf \\000)    # SBAGLIATO: $var è vuota
var=$(printf '\000X')    # SBAGLIATO: $var contiene solo X
var=$(printf \\000X)    # SBAGLIATO: $var contiene solo X
var=$(printf 'X\000X')  # SBAGLIATO: $var contiene XX
var=$(printf X\\000X)  # SBAGLIATO: $var contiene XX
var="$(printf 'X\000X')" # SBAGLIATO: equivalente a sopra
var="$(printf X\\000X)" # SBAGLIATO: equivalente a sopra
var=$'\000'             # SBAGLIATO anche così!
var=$'\000'             # SBAGLIATO anche così!
</pre>
</pre>


Riga 522: Riga 574:
           wc -l)                # conto il numero di righe  
           wc -l)                # conto il numero di righe  


echo "La directory prova contiene ${num_file} file" # restituisce 2 invece di 1
printf %s\\n "La directory prova contiene ${num_file} file" # restituisce 2 invece di 1


# forma corretta
# forma corretta
Riga 529: Riga 581:
           wc -c)                        # conto il numero di caratteri
           wc -c)                        # conto il numero di caratteri


echo "La directory prova contiene ${num_file} file" # restituisce 1
printf %s\\n "La directory prova contiene ${num_file} file" # restituisce 1


# pulizia
# pulizia
Riga 571: Riga 623:
   # il blocco è eseguito solo se un comando fallisce
   # il blocco è eseguito solo se un comando fallisce
   retval=$?
   retval=$?
   echo "ERRORE (exit status: $retval)" >&2
   printf %s\\n "ERRORE (exit status: $retval)" >&2
   exit $retval
   exit $retval
}
}
Riga 609: Riga 661:
|Verificata_da=
|Verificata_da=
:[[Utente:S3v|S3v]] (in Bash tips)
:[[Utente:S3v|S3v]] (in Bash tips)
:[[Utente:HAL 9000|HAL 9000]] 15:34, 12 lug 2014 (CEST)
:[[Utente:HAL 9000|HAL 9000]] 12:00, 14 lug 2014 (CEST)
|Estesa_da=
|Estesa_da=
:[[Utente:S3v|S3v]] (in Bash tips)
:[[Utente:S3v|S3v]] (in Bash tips)
3 581

contributi