Crea sito
22 Ottobre 2020

Officine Informatiche Roma

ICT SERVICES ROMA – BAZAAR INFORMATICO

LINUX COMMAND LINE 7 – Il mondo in una Shell

12 min read
In questo capitolo, esamineremo parte della "magia" che si verifica sulla riga di comando quando si preme il tasto Invio. Mentre esamineremo alcune caratteristiche interessanti e complesse della shell, lo faremo con un solo nuovo comando: echo Visualizza una riga di testo Espansione Ogni volta che digitiamo un comando e premiamo il tasto Invio, bash esegue diverse sostituzioni sul testo prima che esegua il nostro comando. Abbiamo visto un paio di casi in cui una semplice sequenza di caratteri, ad esempio *, può avere molto significato per la shell. Il processo che rende possibile ciò si chiama espansione. Con l'espansione, entriamo in qualcosa e si espande in qualcos'altro prima che la shell agisca su di essa. Per dimostrare cosa intendiamo con questo, diamo un'occhiata al comando echo. echo è una shell incorporata che esegue un compito molto semplice. Stampa i suoi argomenti di testo sull'output standard.

In questo capitolo, esamineremo parte della “magia” che si verifica sulla riga di comando quando si preme il tasto Invio. Mentre esamineremo alcune caratteristiche interessanti e complesse della shell, lo faremo con un solo nuovo comando:

 echo Visualizza una riga di testo

 Espansione

Ogni volta che digitiamo un comando e premiamo il tasto Invio, bash esegue diverse sostituzioni sul testo prima che esegua il nostro comando. Abbiamo visto un paio di casi in cui una semplice sequenza di caratteri, ad esempio *, può avere molto significato per la shell. Il processo che rende possibile ciò si chiama espansione. Con l’espansione, entriamo in qualcosa e si espande in qualcos’altro prima che la shell agisca su di essa. Per dimostrare cosa intendiamo con questo, diamo un’occhiata al comando echo. echo è una shell incorporata che esegue un compito molto semplice. Stampa i suoi argomenti di testo sull’output standard.

me @ linuxbox ~] $ echo questo è un test

Questo è un test abbastanza semplice. Viene visualizzato qualsiasi argomento passato a eco. Proviamo un altro esempio.

[[email protected] ~]$ echo *

Desktop Documents ls-output.txt Music Pictures Public Templates Videos

 Cosa è appena successo? …Perché non è stata eseguita la stampa eco *?

Come ricordiamo dal nostro lavoro con i caratteri jolly, il carattere * significa che corrisponde a qualsiasi carattere in un nome file, ma ciò che non abbiamo visto nella nostra discussione originale è stato come la shell lo fa. La risposta piu’ semplice è che la shell espande il * in qualcos’altro (in questo caso, i nomi dei file nella directory di lavoro corrente) prima dell’esecuzione del comando echo.

Quando si preme il tasto Invio, la shell espande automaticamente tutti i caratteri qualificanti sulla riga di comando prima dell’esecuzione del comando stesso , quindi il comando echo non ha mai visto *, ma solo il suo risultato espanso. Sapendo questo, possiamo vedere quale e’ il risultato previsto con echo

Espansione del nome percorso

Il meccanismo con cui funzionano i caratteri jolly si chiama espansione del nome percorso (pathname expansion).

Se proviamo alcune delle tecniche che abbiamo utilizzato nei capitoli precedenti, vedremo che sono davvero espansioni. Data una home directory che assomiglia a questa:

[[email protected] ~]$ ls

Desktop ls-output.txt                    Pictures               Template

Documents Music                           Public                   Videos

potremmo effettuare le seguenti espansioni:

[me @ linuxbox ~] $ echo D *

Documenti desktop

e questo:

[me @ linuxbox ~] $ echo * s

Documenti Immagini Modelli Modelli Video

o anche questo:

[me @ linuxbox ~] $ echo [[: upper:]] *

Documenti desktop Immagini musicali Modelli pubblici Video

e guardando oltre la nostra home directory, potremmo ottenere:

[[email protected] ~]$ echo /usr/*/share

/usr/kerberos/share /usr/local/share

Espansione del percorso dei file nascosti

Come sappiamo, i nomi dei file che iniziano con un carattere punto sono nascosti.

L’espansione del nome percorso rispetta anche questo comportamento. Un’espansione come la seguente non rivela i file nascosti:

echo *

A prima vista potrebbe sembrare che potremmo includere file nascosti in un fileespansione avviando il modello con un periodo iniziale, come questo:

echo .*

Funziona quasi. Tuttavia, se esaminiamo attentamente i risultati, vedremo che i nomi. e .. apparirà anche nei risultati. Poiché questi nomi si riferiscono alla directory di lavoro corrente e alla sua directory padre, l’utilizzo di questo modello produrrà probabilmente un risultato errato. Possiamo vedere questo se proviamo il seguente comando:

ls -d. * | less

Per eseguire meglio l’espansione del percorso in questa situazione, dobbiamo utilizzare uno schema più specifico.

echo .[!.]*

Questo modello si espande in ogni nome file che inizia con un solo punto seguito da altri caratteri.

Funzionerà correttamente con la maggior parte dei file nascosti (sebbene non includa ancora nomi di file con più periodi iniziali).

Il comando ls con l’opzione -A (“quasi tutto”) fornirà un elenco corretto di file nascosti. ls -A

Espansione Tilde

Come possiamo ricordare dalla nostra introduzione al comando cd, il carattere tilde (~) ha un significato speciale. Se utilizzato all’inizio di una parola, si espande nel nome della home directory dell’utente nominato o, se nessun utente viene nominato, della home directory dell’utente corrente.

[me @ linuxbox ~] $ echo ~

/ Home me /

Se l’utente “pippo” ha un account, si espande in questo:

[me @ linuxbox ~] $ echo ~ foo

/ Home / foo

Espansione aritmetica

La shell consente all’aritmetica di essere eseguita per espansione. Questo ci consente di utilizzare il prompt della shell come calcolatrice.

[me @ linuxbox ~] $ echo $ ((2 + 2))

4

L’espansione aritmetica utilizza il seguente modulo:

$ ((Espressione))

dove Espressione è un’espressione aritmetica costituita da valori e operatori aritmetici. L’espansione aritmetica supporta solo numeri interi (numeri interi, senza decimali) ma può eseguire diverse operazioni.

La tabella descrive alcuni degli operatori supportati.

Tabella: Operatori aritmetici

Descrizione                     Operatore

+                                             Somma

–                                              Sottrazione

*                                             Moltiplicazione

/                                             Divisione (supporta solo numeri interi )

%                                            Modulo, che significa semplicemente “resto”

**                                          Elevazione a n-potenza

Gli spazi non sono significativi nelle espressioni aritmetiche e le espressioni possono essere nidificate. Ad esempio, per moltiplicare 5 al quadrato per 3, possiamo usare questo:

[me @ linuxbox ~] $ echo $ (($ ((5 ** 2)) * 3))

75

Le parentesi singole possono essere utilizzate per raggruppare più sottoespressioni. Con questa tecnica, possiamo riscrivere l’esempio precedente e ottenere lo stesso risultato usando una sola espansione anziché due.

[me @ linuxbox ~] $ echo $ (((5 ** 2) * 3))

75

Ecco un esempio usando gli operatori divisione e resto. Notare l’effetto della divisione intera.

[me @ linuxbox ~] $ echo Cinque diviso per due è uguale a $ ((5/2))

Cinque diviso per due uguali 2

[me @ linuxbox ~] $ echo con $ ((5% 2)) rimasto.

con 1 rimasto.

Espansione e Parentesi Graffe

Forse l’espansione più strana si chiama espansione di parentesi graffe.

Con esso, è possibile creare più stringhe di testo da un modello contenente parentesi graffe. Ecco un esempio:

[[email protected] ~]$ echo Front-{A,B,C}-Back

Front-A-Back Front-B-Back Front-C-Back

I motivi da considerare e ampliare contengono una parte iniziale chiamata a preambolo e una parte finale chiamata postscript.

L’espressione parentesi graffa stessa può contenere un elenco di stringhe separato da virgole o un intervallo di numeri interi o singoli caratteri.

Il modello potrebbe non contenere spazi bianchi non quotati.

Ecco un esempio usando un intervallo di numeri interi:

[[email protected] ~]$ echo Number_{1..5}

Number_1 Number_2 Number_3 Number_4 Number_5

In bash versione 4.0 e successive, anche gli interi possono essere a zero:

[[email protected] ~]$ echo {01..15}

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15

[[email protected] ~]$ echo {001..15}

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015

Ecco una serie di lettere in ordine inverso:

[[email protected] ~]$ echo {Z..A}

Z Y X W V U T S R Q P O N M L K J I H G F E D C B A

Le espansioni di parentesi graffe possono essere nidificate.

[me @ linuxbox ~] $ echo a {A {1,2}, B {3,4}} b

aA1b aA2b aB3b aB4b

A cosa serve questo?

L’applicazione più comune è fare elenchi di file o directory da creare.

Ad esempio, se fossimo fotografi e avessimo una vasta raccolta di immagini che volevamo organizzare in anni e mesi, la prima cosa che potremmo fare è creare una serie di directory denominate in formato numerico “Anno-Mese”. In questo modo, i nomi delle directory verranno ordinati in ordine cronologico.

Potremmo scrivere un elenco completo di directory, ma è un sacco di lavoro ed è soggetto a errori.

Invece, potremmo fare questo:

[me @ linuxbox ~] $ mkdir foto

[me @ linuxbox ~] $ cd Foto

[me @ linuxbox Photos] $ mkdir {2007..2009} – {01..12}

[me @ linuxbox Photos] $ ls

2007-01 2007-07 2008-01 2008-07 2009-01 2009-07

2007-02 2007-08 2008-02 2008-08 2009-02 2009-08

2007-03 2007-09 2008-03 2008-09 2009-03 2009-09

2007-04 2007-10 2008-04 2008-10 2009-04 2009-10

2007-05 2007-11 2008-05 2008-11 2009-05 2009-11

2007-06 2007-12 2008-06 2008-12 2009-06 2009-12

Espansione dei parametri

Parleremo solo brevemente dell’espansione dei parametri in questo capitolo, ma lo tratteremo ampiamente in seguito. È una funzionalità più utile negli script di shell che direttamente sulla riga di comando. Molte delle sue capacità hanno a che fare con la capacità del sistema di archiviare piccoli blocchi di dati e di assegnare un nome a ciascun blocco. Molti di questi blocchi, chiamati più correttamente variabili, sono disponibili per l’esame. Ad esempio, la variabile denominata USER contiene il tuo nome utente.

Per invocare l’espansione dei parametri e rivelare il contenuto di USER, devi fare questo:

[me @ linuxbox ~] $ echo $ USER

me

Per visualizzare un elenco di variabili disponibili, prova questo:

[me @ linuxbox ~] $ printenv | less

Potresti aver notato che con altri tipi di espansione, se si digita male un parametro, l’espansione non avrà luogo e il comando echo visualizzerà semplicemente il motivo sbagliato.

Con l’espansione dei parametri, se si scrive male il nome di una variabile, l’espansione avrà comunque luogo ma si tradurrà in una stringa vuota.

[me @ linuxbox ~] $ echo $ SUER

[me @ linuxbox ~] $

Sostituzione comando

La sostituzione dei comandi ci consente di utilizzare l’output di un comando come espansione.

[me @ linuxbox ~] $ echo $ (ls)

Documenti desktop ls-output.txt Immagini musicali Modelli pubblici Video

Uno dei miei preferiti è qualcosa del genere:

[me @ linuxbox ~] $ ls -l $ (che cp)

-rwxr-xr-x 1 radice radice 71516 2007-12-05 08:58 / bin / cp

Qui abbiamo passato i risultati di cui cp come argomento al comando ls, ottenendo così l’elenco del programma cp senza dover conoscere il suo percorso completo. Non siamo limitati a semplici comandi. È possibile utilizzare intere pipeline (qui viene mostrato solo l’output parziale).

[[email protected] ~]$ file $(ls -d /usr/bin/* | grep zip)

/usr/bin/bunzip2: symbolic link to `bzip2′

/usr/bin/bzip2: ELF 32-bit LSB executable, Intel 80386, version 1

(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/bzip2recover: ELF 32-bit LSB executable, Intel 80386, version 1

(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/funzip: ELF 32-bit LSB executable, Intel 80386, version 1

(SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

/usr/bin/gpg-zip: Bourne shell script text executable

/usr/bin/gunzip: symbolic link to `../../bin/gunzip’

/usr/bin/gzip: symbolic link to `../../bin/gzip’

/usr/bin/mzip: symbolic link to `mtools’

In questo esempio, i risultati della pipeline sono diventati l’elenco degli argomenti del comando file.

Esiste una sintassi alternativa per la sostituzione dei comandi nei programmi shell precedenti supportata anche in bash.

Usa i backquotes invece del simbolo del dollaro e delle parentesi.

[me @ linuxbox ~] $ ls -l `which cp`

-rwxr-xr-x 1 radice radice 71516 2007-12-05 08:58 / bin / c

QUOTAZIONI

Ora che abbiamo visto in quanti modi la shell può eseguire espansioni, è tempo di imparare come possiamo controllarla.

Prendi ad esempio quanto segue:

[[email protected] ~]$ echo this is a test

this is a test

o questo:

[[email protected] ~]$ echo The total is $100.00

The total is 00.00

Nel primo esempio, la suddivisione delle parole dalla shell ha rimosso gli spazi extra dall’elenco di argomenti del comando echo.

Nel secondo esempio, l’espansione dei parametri ha sostituito una stringa vuota per il valore di $ 1 perché era una variabile non definita.

La shell fornisce un meccanismo chiamato quoting per sopprimere selettivamente espansioni indesiderate.

Virgolette

Il primo tipo di quotazione che vedremo sarà le doppie virgolette. Se inseriamo il testo tra virgolette doppie, tutti i caratteri speciali utilizzati dalla shell perdono il loro significato speciale e vengono trattati come caratteri ordinari. Le eccezioni sono $ (segno del dollaro), \ (barra rovesciata) e `(barra retroversa). Ciò significa che la suddivisione delle parole, l’espansione del percorso, l’espansione della tilde e l’espansione del controvento sono soppressi; tuttavia, l’espansione dei parametri, l’espansione aritmetica e la sostituzione dei comandi vengono comunque eseguite.

Usando le virgolette doppie, possiamo far fronte a nomi di file contenenti spazi incorporati.

Supponiamo lo sfortunato caso di un file chiamato two words.txt.

Se provassimo a usarlo sulla riga di comando, la suddivisione delle parole farebbe in modo che questo venga trattato come due argomenti separati anziché come argomento singolo desiderato.

[[email protected] ~]$ ls -l two words.txt

ls: cannot access two: No such file or directory

ls: cannot access words.txt: No such file or directory

Usando le virgolette doppie, fermiamo la divisione della parola e otteniamo il risultato desiderato; inoltre, possiamo persino riparare il danno. Cosi:

[[email protected] ~]$ ls -l “two words.txt”

-rw-rw-r– 1 me me 18 2018-02-20 13:03 two words.txt

[[email protected] ~]$ mv “two words.txt” two_words.txt

Là! Ora non dobbiamo continuare a digitare quelle fastidiose doppie virgolette. Ricorda che l’espansione dei parametri, l’espansione aritmetica e la sostituzione dei comandi avvengono ancora tra virgolette.

[[email protected] ~]$ echo “$USER $((2+2)) $(cal)”

me 4 February 2020

Su Mo Tu We Th Fr Sa

1

2 3 4 5 6 7 8

9 10 11 12 13 14 15

16 17 18 19 20 21 22

23 24 25 26 27 28 29

Prendiamoci un momento  per esaminare l’effetto delle doppie virgolette sulla sostituzione dei comandi. Innanzitutto, esaminiamo un po ‘più a fondo come funziona la suddivisione delle parole. Nel nostro esempio precedente, abbiamo visto come la suddivisione delle parole sembra rimuovere gli spazi extra nel nostro testo.

[[email protected] ~]$ echo this is a         test

this is a test

Per impostazione predefinita, la suddivisione delle parole cerca la presenza di spazi, tabulazioni e nuove righe (caratteri di avanzamento riga) e li considera come delimitatori tra le parole.

Ciò significa che spazi, tabulazioni e nuove righe non quotati non sono considerati parte del testo.

Servono solo come separatori. Poiché separano le parole in diversi argomenti, la nostra riga di comando di esempio contiene un comando seguito da quattro argomenti distinti. Se aggiungiamo virgolette doppie:

[[email protected] ~]$ echo “this is a test”

this is a test

Quindi viene soppressa, la divisione delle parole e gli spazi incorporati, non vengono trattati come delimitatori; piuttosto, diventano questi, parte dell’argomento. Una volta aggiunte le doppie virgolette, la nostra riga di comando contiene un comando seguito da un singolo argomento. Il fatto che i newline siano considerati delimitatori dal meccanismo di suddivisione delle parole provoca un interessante, seppur sottile, effetto sulla sostituzione dei comandi.

Considera quanto segue:

[[email protected] ~]$ echo $(cal)

February 2020 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

18 19 20 21 22 23 24 25 26 27 28 29

[[email protected] ~]$ echo “$(cal)”

February 2020

Su Mo Tu We Th Fr Sa

1

2 3 4 5 6 7 8

9 10 11 12 13 14 15

16 17 18 19 20 21 22

23 24 25 26 27 28 29

Nel primo caso, la sostituzione del comando non quotata ha prodotto una riga di comando contenente 38 argomenti. Nel secondo, ha portato a una riga di comando con un argomento che include gli spazi incorporati e le nuove righe.

Virgolette  singole

Se dobbiamo eliminare tutte le espansioni, utilizziamo virgolette singole.

Ecco un confronto tra virgolette, virgolette doppie e virgolette singole:

[me @ linuxbox ~] $ echo text ~ / *. txt {a, b} $ (echo foo) $ ((2 + 2)) $ USER

text /home/me/ls-output.txt a b foo 4 me

[[email protected] ~]$ echo “text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER”

text ~/*.txt {a,b} foo 4 me

[[email protected] ~]$ echo ‘text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER’

text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER

Come possiamo vedere, ad ogni successivo livello di quotazione, sempre più espansioni vengono soppresse.

Carattere escape

A volte vogliamo citare solo una singola parola. Per fare ciò, possiamo precedere una parola con una barra rovesciata, che in questo contesto è chiamato carattere di escape.

Spesso questo viene fatto tra virgolette doppie per impedire selettivamente un’espansione.

[[email protected] ~]$ echo “The balance for user $USER is: \$5.00”

The balance for user me is: $5.00

È anche comune usare l’escaping per eliminare il significato speciale di un carattere in un nome file. Ad esempio, è possibile utilizzare caratteri nei nomi dei file che normalmente hanno un significato speciale per la shell. Questi includono $,!, &, Spazi e altri. Per includere un carattere speciale in un nome file, possiamo fare questo:

[[email protected] ~]$ mv bad\&filename good_filename

Per consentire la visualizzazione di un carattere backslash, digitare \\.

Si noti che all’interno di virgolette singole, la barra rovesciata perde il suo significato speciale e viene trattata come un carattere ordinario.

Sequenze di escape e  barra rovesciata

Oltre al suo ruolo di carattere di escape, la barra rovesciata viene utilizzata come parte di una notazione per rappresentare alcuni caratteri speciali chiamati codici di controllo.

I primi 32 caratteri nello schema di codifica ASCII vengono utilizzati per trasmettere comandi a dispositivi simili utilizzati nelle telescriventi. Alcuni di questi codici sono familiari (tabulazione, backspace, avanzamento riga e ritorno a capo), mentre altri non lo sono (null, fine della trasmissione e riconoscimento).

La Tabella 7-2 elenca alcune delle sequenze di escape backslash comuni.

Tabella 7-2: sequenze di escape barra rovesciata

Sequenza                                                            Significato

\a                 Bell (un avviso che fa emettere un  segnale acustico al computer)

\b                                                                           Backspace

\n   Newline; su sistemi simili a Unix, questo produce un avanzamento di riga

\r                                                                            Ritorno a capo

\t                                                                            Tab

L’idea alla base di questa rappresentazione usando la barra rovesciata è nata nel linguaggio di programmazione C ed è stata adottata da molti altri, inclusa la shell. L’aggiunta dell’opzione -e all’eco consentirà l’interpretazione delle sequenze di escape.

Puoi anche metterli all’interno di $ ”. Qui, usando il comando sleep, si crea una semplice stringa di programma che aspetta solo il numero specificato di secondi per poi uscire, possiamo quindi  creare un timer per un conto alla rovescia primitivo:

sleep 10; echo -e “Time’s up\a”

Potremmo anche fare questo:

sleep 10; echo “Time’s up” $’\a’

Riassumendo

Man mano che andiamo avanti con l’uso della shell, scopriremo che espansioni e quotazioni verranno utilizzate con frequenza crescente, quindi ha senso comprendere bene il modo in cui funzionano. In effetti, si potrebbe sostenere che sono le materie più importanti da imparare sulla shell.  Senza una corretta comprensione dell’espansione, la shell sarà sempre una fonte di mistero e confusione, con gran parte del suo potenziale potere sprecato.

Translate »