Bash scripting - espansioni non quotabili: differenze tra le versioni

m
m (correzione classe con file nascosti)
 
(9 versioni intermedie di 2 utenti non mostrate)
Riga 1: Riga 1:
{{Bash_scripting}}
{{Bash scripting}}
=Espansioni non quotabili=
__TOC__
Le espansioni trattate nelle sezioni successive avvengono unicamente in stringhe non quotate, almeno limitatamente ai caratteri speciali che le attivano, e sono attivabili soltanto da caratteri diversi dal '''$'''.
Le espansioni trattate nelle sezioni successive avvengono unicamente in stringhe non quotate, almeno limitatamente ai caratteri speciali che le attivano, e sono attivabili soltanto da caratteri diversi dal '''$'''.


Riga 7: Riga 7:
Inoltre l'espansione di tilde, che è sempre espansa in una singola stringa, è l'unica possibile in un'assegnazione tra le espansioni non quotabili.
Inoltre l'espansione di tilde, che è sempre espansa in una singola stringa, è l'unica possibile in un'assegnazione tra le espansioni non quotabili.


==Espansione di tilde==
== Espansione di tilde ==
<!--
Nota: *NON* modificare il nome della sezione, perché è usato in un'altra guida
-->
Sintassi:
Sintassi:
* <code>~</code> (per digitarlo con tastiera con layout italiano: <code>Ctrl-ì</code>) si espande alla home, se non è quotata (equivalente all'uso di ${HOME}, che può essere quotata);
* <code>~</code> (per digitarlo con tastiera con layout italiano: <code>Alt-Gr+ì</code>) si espande alla home, se non è quotata (equivalente all'uso di ${HOME}, che può essere quotata);
* <code>~utente</code> si espande alla home di un dato utente, se esiste, ma la stringa non può essere quotata né essere una variabile.
* <code>~utente</code> si espande alla home di un dato utente, se esiste, ma la stringa non può essere quotata né essere una variabile.


Riga 40: Riga 43:
Si noti che il percorso può anche non esistere, infatti soltanto le stringhe <code>~/</code> e <code>~utente/</code> sono espanse. Non è infatti un'espansione di percorso.
Si noti che il percorso può anche non esistere, infatti soltanto le stringhe <code>~/</code> e <code>~utente/</code> sono espanse. Non è infatti un'espansione di percorso.


==Espansione di percorso==
== Espansione di percorso ==
{{Box | File | Su Unix e Unix-like per file si può intendere sia un file regolare, ma anche una directory, un link simbolico, una pipe, un socket, un device, ecc...
{{Box | File | Su Unix e Unix-like per file si può intendere sia un file regolare, ma anche una directory, un link simbolico, una pipe, un socket, un device, ecc...


Riga 65: Riga 68:
**il carattere <code>!</code> può essere contenuto per il suo valore letterale in una classe purché non in prima posizione, mentre il carattere <code>-</code> è considerato letteralmente soltanto in prima posizione (o seconda se dopo <code>!</code>) e in ultima posizione.
**il carattere <code>!</code> può essere contenuto per il suo valore letterale in una classe purché non in prima posizione, mentre il carattere <code>-</code> è considerato letteralmente soltanto in prima posizione (o seconda se dopo <code>!</code>) e in ultima posizione.


Esistono inoltre delle classi già predefinite, utilizzabili all'interno di '''[ ]''' con altre parentesi quadre e la seguente sintassi:
* '''[:lower:]''', per caratteri alfabetici minuscoli (a-z);
* '''[:upper:]''', per caratteri alfabetici maiuscoli (A-Z);
* '''[:alpha:]''', per caratteri alfabetici minuscoli e maiuscoli (a-zA-Z);
* '''[:digit:]''', per caratteri numerici (0-9);
* '''[:xdigit:]''', per caratteri numerici in base esadecimale (0-9A-F);
* '''[:alnum:]''', per caratteri alfabetici e numerici (a-zA-Z0-9);
* '''[:word:]''', per caratteri alfabetici, numerici e underscore (a-zA-Z0-9_);
* '''[:punct:]''', per caratteri di punteggiatura, accenti, virgolette, parentesi, underscore, operatori e tutti i simboli presenti tra i primi 127 caratteri ASCII;
* '''[:graph:]''', per caratteri che hanno una rappresentazione grafica visibile (niente spazi), ossia tutto ciò che appartiene alle classi '''[:word:]''' e '''[:punct:]'''. Corrisponde a tutti i caratteri ASCII compresi tra 21 e 126;
* '''[:print:]''', corrisponde alla classe '''[:graph:]''' con l'aggiunta del carattere spazio (non tabulazioni o "a capo"), ossia ai caratteri ASCII compresi tra 20 e 126;
* '''[:blank:]''', per caratteri di spaziatura orizzontale che lasciano spazi vuoti, ossia spazio e tabulazione (orizzontale);
* '''[:space:]''', per tutti i caratteri di spaziatura, ossia spazio, tabulazione orizzontale e verticale, interruzioni (''break''), ritorno a inizio riga (''carriage return'') e "a capo";
* '''[:cntrl:]''', per tutti i caratteri di controllo, ossia i primi 128 caratteri ASCII che non appartengono alla classe '''[:print:]'''. Non include lo spazio, ma include tutti gli altri caratteri presenti in '''[:space:]'''; e in generale i caratteri ASCII da 0 a 19, e il carattere ASCII n. 127;
* '''[:ascii:]''', per tutti i caratteri ASCII da 0 a 127, ed è equivalente alle due classi '''[:print:]''' e '''[:cntrl:]'''.
=== Esempi di espansioni di percorso ===
Se un nome di file non include il percorso assoluto (iniziante con la directory radice '''/''') o relativo (iniziante con '''./''' oppure '''../''', dalla directory corrente e da quella superiore rispettivamente), di default si assume che sia nella directory corrente. Tuttavia per evitare ambiguità con i nomi delle opzioni di alcuni comandi, in presenza di possibili nomi di file inizianti con il trattino '''-''', in particolare se la parte iniziale del file è generata dall'espansione di percorso, è sempre bene rendere esplicito il percorso relativo premettendo '''./''' al nome del file.
Se un nome di file non include il percorso assoluto (iniziante con la directory radice '''/''') o relativo (iniziante con '''./''' oppure '''../''', dalla directory corrente e da quella superiore rispettivamente), di default si assume che sia nella directory corrente. Tuttavia per evitare ambiguità con i nomi delle opzioni di alcuni comandi, in presenza di possibili nomi di file inizianti con il trattino '''-''', in particolare se la parte iniziale del file è generata dall'espansione di percorso, è sempre bene rendere esplicito il percorso relativo premettendo '''./''' al nome del file.


Riga 72: Riga 92:
* <code>./*</code> si espande a tutti i file non nascosti nella directory corrente;
* <code>./*</code> si espande a tutti i file non nascosti nella directory corrente;
* <code>./*.txt</code> espande a tutti i file con estensione .txt ('''NOTA:''' anche directory e qualsiasi file non regolare avente tale estensione);
* <code>./*.txt</code> espande a tutti i file con estensione .txt ('''NOTA:''' anche directory e qualsiasi file non regolare avente tale estensione);
* <code>./*."${estensione}"</code> espande dopo aver espanso la variabile (contrariamente a ~), che può anche essere quotata;
* <code>./*.[tT][xX][tT]</code> espande a tutti i file con estensione txt (ignorando maiuscole e minuscole);
* <code>"./${nome}"*</code> espande a tutti i file inizianti con ${nome};
* <code>./*."${estensione}"</code> espande a tutti i file con l'estensione indicata dalla variabile quotata;
* <code>"./${nome}"*</code> espande a tutti i file inizianti con il prefisso indicato dalla variabile quotata;
* <code>./*/</code> espande a tutte le directory non nascoste;
* <code>./*/</code> espande a tutte le directory non nascoste;
* <code>./[a-zA-Z]*</code> espande a tutti i file inizianti con una lettera qualsiasi;
* <code>./<nowiki>[[:alpha:]]</nowiki>*</code> equivalente a sopra;
* <code>./<nowiki>[[:word:]]</nowiki>*</code> espande a tutti i file inizianti con lettere maiuscole, minuscole, numeri e underscore;
* <code>./.*</code> espande a tutti i file nascosti ('''ATTENZIONE:''' comprese "'''.'''" e "'''..'''", ossia directory corrente e superiore);
* <code>./.*</code> espande a tutti i file nascosti ('''ATTENZIONE:''' comprese "'''.'''" e "'''..'''", ossia directory corrente e superiore);
* <code>./[a-zA-Z]*</code> espande a tutti i file inizianti con una lettera qualsiasi;
* <code>./*.[tT][xX][tT]</code> espande a tutti i file con estensione txt (ignorando maiuscole e minuscole);
* <code>./.[!.]*</code> espande a tutti i file nascosti di almeno due caratteri in cui il secondo non è un punto (non espande a '''.''' e '''..''', ma nemmeno a possibili file nascosti inizianti con '''..''');
* <code>./.[!.]*</code> espande a tutti i file nascosti di almeno due caratteri in cui il secondo non è un punto (non espande a '''.''' e '''..''', ma nemmeno a possibili file nascosti inizianti con '''..''');
* <code>./..?*</code> espande a tutti i file nascosti di almeno tre caratteri in cui il secondo è un punto (tutti i file nascosti saltati dal precedente, ma sempre escludendo '''.''' e '''..''');
* <code>./..?*</code> espande a tutti i file nascosti di almeno tre caratteri in cui il secondo è un punto (tutti i file nascosti saltati dal precedente, ma sempre escludendo '''.''' e '''..''');
* <code>./.[!.]* ./..?*</code> espande a tutti i file nascosti, esclusi '''.''' e '''..''' (''POSIX'').
* <code>./.[!.]* ./..?*</code> espande a tutti i file nascosti, esclusi '''.''' e '''..''' ([[POSIX]]).


È importante sapere che, se nessun file combacia con un dato pattern, allora l'espansione '''non''' viene effettuata e i caratteri mantengono il loro valore letterale. E inoltre <code>*</code>, <code>?</code>, <code>[</code> e <code>]</code> sono caratteri validi per un nome di file.
È importante sapere che, se nessun file combacia con un dato pattern, allora l'espansione '''non''' viene effettuata e i caratteri mantengono il loro valore letterale. E inoltre <code>*</code>, <code>?</code>, <code>[</code> e <code>]</code> sono caratteri validi per un nome di file.
Riga 90: Riga 112:
   fi
   fi
done</pre>
done</pre>
Il pattern <code>*</code> è l'unico in grado di sostituire un numero qualsiasi di caratteri (zero o più), mentre <code>?</code> e le classi sempre e soltanto un singolo carattere. Si faccia attenzione però che tutti i pattern, e non solo quelli composti da <code>*</code>, possono generare liste di percorsi, in presenza di fili multipli con lo stesso prefisso e/o suffisso. Per esempio il pattern '''./a?c''' può espandersi alla lista ''./abc ./aBC ./acc'', se esistono questi tre file nella directory corrente (e nessun altro di tre caratteri che inizi con '''a''' e termini con '''c''').  
Il pattern <code>*</code> è l'unico in grado di sostituire un numero qualsiasi di caratteri (zero o più), mentre <code>?</code> e le classi sempre e soltanto un singolo carattere. Si faccia attenzione però che tutti i pattern, e non solo quelli composti da <code>*</code>, possono generare liste di percorsi, in presenza di fili multipli con lo stesso prefisso e/o suffisso. Per esempio il pattern '''./a?c''' può espandersi alla lista ''./abc ./aBC ./acc'', se esistono questi tre file nella directory corrente (e nessun altro di tre caratteri che inizi con '''a''' e termini con '''c''').


===Espansione di percorso con nuovi file===
=== Espansione di percorso con nuovi file ===
L'espansione di percorso può fallire anche se non trova corrispondenze nella parte non riguardante i caratteri speciali, perché i caratteri speciali sono espansi in funzione di tutta la stringa. Questo significa che deve esistere il risultato dell'espansione, considerando il percorso nella sua interezza, prima dell'esecuzione di un qualsiasi comando.
L'espansione di percorso può fallire anche se non trova corrispondenze nella parte non riguardante i caratteri speciali, perché i caratteri speciali sono espansi in funzione di tutta la stringa. Questo significa che deve esistere il risultato dell'espansione, considerando il percorso nella sua interezza, prima dell'esecuzione di un qualsiasi comando.


Riga 123: Riga 145:
</pre>
</pre>


===Cambiare i risultati dell'espansione===
=== Cambiare i risultati dell'espansione ===
Il comportamento di default dell'espansione può essere cambiato in bash (non ''POSIX''), tramite <code>shopt -s</code> (''set''):
Il comportamento di default dell'espansione può essere cambiato in bash (non ''POSIX''), tramite <code>shopt -s</code> (''set''):
* '''nullglob''' espande a "niente" se non trova nessun file con un dato pattern, rendendo superfluo il controllo sull'esistenza;
* '''nullglob''' espande a "niente" se non trova nessun file con un dato pattern, rendendo superfluo il controllo sull'esistenza;
Riga 138: Riga 160:
Per disabilitare un'opzione, ripristinando il default, si può utilizzare <code>shopt -u</code> (''unset'').
Per disabilitare un'opzione, ripristinando il default, si può utilizzare <code>shopt -u</code> (''unset'').


===Esempio: cambiare l'estensione ai file regolari===
=== Esempio: cambiare l'estensione ai file regolari ===
Rinomina tutti i file regolari <code>*.txt</code> della directory corrente in <code>*.log</code>, tramite il comando esterno <code>mv</code>:
Rinomina tutti i file regolari <code>*.txt</code> della directory corrente in <code>*.log</code>, tramite il comando esterno <code>mv</code>:


Riga 151: Riga 173:
Si noti che utilizzando <code>[ '''-f''' ... ]</code> in luogo di <code>[ '''-e''' ... ]</code>, si saltano anche tutti i file che non sono regolari, e che potrebbero essere restituiti dall'espansione di percorso.
Si noti che utilizzando <code>[ '''-f''' ... ]</code> in luogo di <code>[ '''-e''' ... ]</code>, si saltano anche tutti i file che non sono regolari, e che potrebbero essere restituiti dall'espansione di percorso.


==Espansione di parentesi (graffa)==
== Espansione di parentesi (graffa) ==
In '''bash''' (non ''POSIX'') se i caratteri <code>{</code> e <code>}</code> non sono quotati, e non sono preceduti dal carattere di escape <code>\</code>, possono essere espansi con due diverse sintassi per generare una lista di stringhe. E più espansioni di parentesi possono essere annidate.
In '''bash''' (non ''POSIX'') se i caratteri <code>{</code> e <code>}</code> non sono quotati, e non sono preceduti dal carattere di escape <code>\</code>, possono essere espansi con due diverse sintassi per generare una lista di stringhe. E più espansioni di parentesi possono essere annidate.


Questa espansione avviene prima di tutte le altre, e il risultato può passare per tutte le altre espansioni. Non può avvenire in un'assegnazione, se non all'interno di altre espansioni.
Questa espansione avviene prima di tutte le altre, e il risultato può passare per tutte le altre espansioni. Non può avvenire in un'assegnazione, se non all'interno di altre espansioni.


===Con indici di intervallo===
=== Con indici di intervallo ===
Sintassi: <code>prefisso{x..y[..z]}suffisso</code>
Sintassi: <code>prefisso{x..y[..z]}suffisso</code>


Riga 173: Riga 195:
</pre>
</pre>


===Con lista di stringhe===
=== Con lista di stringhe ===
Sintassi: <code>prefisso{stringa1,stringa2,...}suffisso</code>
Sintassi: <code>prefisso{stringa1,stringa2,...}suffisso</code>


Riga 191: Riga 213:
</pre>
</pre>


===Differenze con l'espansione di percorso===
Un altro esempio particolarmente utile potrebbe essere la copia di un file in un'altra directory, il cui percorso assoluto è molto lungo:
<pre>
cp -- /percorso/assoluto/decisamente/lungo/del/file/nomefile /percorso/assoluto/decisamente/lungo/del/file/nomefile.nuovo
</pre>
che si traduce in:
<pre>
cp -- /percorso/assoluto/decisamente/lungo/del/file/{nomefile,nomefile.nuovo}
</pre>
senza bisogno di spostarsi dalla directory corrente. E lo stesso si applica a <code>mv</code> per spostare o rinominare un file.
 
=== Differenze con l'espansione di percorso ===
L'espansione di parentesi graffe:
L'espansione di parentesi graffe:
* non è ''POSIX'', mentre l'espansione di percorso sì;
* non è [[POSIX]], mentre l'espansione di percorso sì;
* espande delle stringhe, non ha importanza a cosa si riferiscono, mentre l'espansione di percorso si espande solo a percorsi esistenti (al tempo dell'espansione, ossia prima dell'esecuzione del comando);
* espande delle stringhe, non ha importanza a cosa si riferiscono, mentre l'espansione di percorso si espande solo a percorsi esistenti (al tempo dell'espansione, ossia prima dell'esecuzione del comando);
* avviene per prima e può contenere altre espansioni (anche quotate, purché non siano quotate le graffe e le virgole), mentre l'espansione di percorso avviene per ultima e può solo essere il risultato di altre espansioni (se non quotate);
* avviene per prima e può contenere altre espansioni (anche quotate, purché non siano quotate le graffe e le virgole), mentre l'espansione di percorso avviene per ultima e può solo essere il risultato di altre espansioni (se non quotate);
Riga 199: Riga 231:


Riguardo l'ultimo punto si consideri per esempio <code>file{1..20}</code>: si espande alla lista (di stringhe!) ''file1 file2 ... file20'', a prescindere che esistano.<br/>
Riguardo l'ultimo punto si consideri per esempio <code>file{1..20}</code>: si espande alla lista (di stringhe!) ''file1 file2 ... file20'', a prescindere che esistano.<br/>
All'opposto <code>file[1-20]</code> non è possibile, nel senso che ha tutt'altro significato. Infatti l'espansione di percorso <code>[1-20]</code> significa: tutti i caratteri tra 1 e 2, e lo 0, ossia equivale alla forma (più comprensibile) <code>[0-2]</code>, perché l'intervallo è possibile solo tra due singoli caratteri all'interno di una classe. E inoltre, al solito con le espansion di percorso, <code>file[0-2]</code> sarebbe espanso ai soli file esistenti tra file0, file1 e file2, e solo se almeno uno dei tre esiste oppure resterebbe letteralmente <code>file[0-2]</code>.
All'opposto <code>file[1-20]</code> non è possibile, nel senso che ha tutt'altro significato. Infatti l'espansione di percorso <code>[1-20]</code> significa: tutti i caratteri tra 1 e 2, e lo 0, ossia equivale alla forma (più comprensibile) <code>[0-2]</code>, perché l'intervallo è possibile solo tra due singoli caratteri all'interno di una classe. E inoltre, al solito con le espansioni di percorso, <code>file[0-2]</code> sarebbe espanso ai soli file esistenti tra file0, file1 e file2, e solo se almeno uno dei tre esiste oppure resterebbe letteralmente <code>file[0-2]</code>.


[[Categoria:Bash]][[Categoria:Bash_Scripting]]
[[Categoria:Bash]][[Categoria:Bash_Scripting]]
3 581

contributi