\

Aqui temos um livro livre e completo sobre Shell

Os sedentos do "saber livre" são muito benvindos.

Você está aqui: TWikiBar > BatePapos > TWikiBarChiacchiere001
Controles: EDITAR ANEXAR MAIS MAIS ALTERACOES IMPRIMIR - Última Atualização: [19 Feb 2013 - V.13]

Chiacchiere da Bar - Parte I

Dialogo tra un Linuxiano e un mouse-dipendente:

    - Che cos'è la Bash?

    - La Bash è il membro più giovane della famiglia Shell.

    - Caspita! Vuoi farmi diventare matto? Prima avevo un dubbio e adesso ne ho due!

    - No, matto lo eri già. Almeno da quando hai deciso di usare quel sistema operativo al quale devi fare il reboot una decina di volte al giorno e che non ti permette di avere il controllo su quel che succede nel tuo computer. Ma per ora lasciamo stare, adesso ti spiego per filo e per segno che cosa sono la Shell e i membri della sua famiglia e alla fine mi dirai: "Dio della Shell! Perché non sono passato prima a Linux?".

L'Ambiente Linux

Per farti capire che cos'è e come funziona la Shell, ti mostrerò prima com'è strutturato l'ambiente Linux. Da' un'occhiata al disegno qua sotto:

Diagramma funzionale del Linux

Nel disegno si vede chiaramente che l' hardware è lo strato più basso ed è formato dai componenti fisici del tuo computer. Tutto attorno c'è il kernel che è il centro e il cuore di Linux ed è ciò che gestisce, controlla e fa funzionare l' hardware. I programmi e i comandi che avvolgono il kernel si utilizzano per portare a termine i compiti per i quali sono stati sviluppati. Infine, lo strato esterno è costituito dalla Shell, chiamata così dalla parola inglese che significa guscio, conchiglia. La Shell è posta tra l'utente e il sistema operativo, così che tutto ciò che interagisce con il sistema passa attraverso questo filtro.

L'Ambiente Shell

Poiché per raggiungere il kernel Linux (il vero obiettivo delle applicazioni) è necessario passare attraverso il filtro della Shell, cerchiamo di capire come essa funziona in modo da sfruttare al massimo i numerosi strumenti che ci offre.

Linux è, per definizione, un sistema multiutente – - non dimentichiamolo mai –- e, per permettere l'accesso a determinati utenti e impedirlo ad altri, c'è un file chiamato /etc/passwd il quale, oltre a fornire i dati per questa funzione di "buttafuori" per Linux, fornisce anche informazioni per il login di quanti hanno superato questa prima barriera. Infatti, l'ultimo campo dei suoi registri informa il sistema riguardo al tipo di Shell in cui l'utente si troverà dopo essersi "loggato" (ARGH!!!).

Pinguim com placa de dica (em inglês) Quando ho detto che l'ultimo campo di /etc/passwd informa il sistema riguardo al tipo di Shell in cui l'utente si troverà dopo essersi "loggato", intendevo tutto questo alla lettera, cioè, se in questo campo del suo registro c'è prog, all'utente che accederà al sistema verrà mostrata la schermata di esecuzione dei programma prog e, al termine dell'esecuzione, si otterrà immediatamente il logout dell'utente. Immagina quanto possiamo aumentare la sicurezza con questo semplice trucco.

Amico mio, ricordi che ti ho parlato della famiglia Shell? Bene, vediamo di capirne qualcosa in più: Shell, che richiama l'immagine di una conchiglia che racchiude il sistema operativo vero e proprio, è il nome generico usato per fare riferimento ai figli di quell'idea venuti alla luce da quando esiste il sistema operativo Unix. Attualmente esistono diversi tipi di Shell, tra i quali spiccano sh (Bourne Shell), ksh (Korn Shell), bash (Bourne Again Shell) e csh (C Shell).

Un'occhiata ai principali tipi di Shell

Bourne Shell (sh)

Sviluppata da Stephen Bourne dei Bell Labs (gli stessi laboratori della AT&T dai quali è uscito Unix), è stata per molti anni la Shell di default del sistema operativo Unix. È anche chiamata Standard Shell perché è stata l'unica per molti anni ed è ancora oggi la più utilizzata grazie al porting per tutti gli ambienti Unix e le distribuzioni Linux.

Korn Shell (ksh)

Sviluppata da David Korn, anch'essa nei Bell Labs, é un superinsieme della sh, cioè contiene tutti gli strumenti della sh e molti altri ancora. La compatibilità totale con la sh fa sì che molti utenti e programmatori della Shell passino a questo ambiente.

Boune Again Shell (bash)

È la Shell più moderna e con un numero di utenti in continua crescita in tutto il mondo sia perché è la Shell di default in Linux, il suo sistema operativo ospite, sia per la grande varietà di comandi, tra i quali sono compresi molte istruzioni tipiche della C Shell.

C Shell (csh)

Sviluppata da Bill Joy della Berkley University, è la Shell più utilizzata negli ambienti *BSD e Xenix. La struttura dei suoi comandi è molto simile a quella del linguaggio C. Il suo grande difetto è stato quello di rinunciare alla compatibilità con la sh per intraprendere una strada tutta sua.

Oltre a questi tipi di Shell ne esistono altri, ma ti parlerò soltanto dei primi tre, chiamandoli genericamente Shell e segnalandone le rispettive caratteristiche quando sarà il momento.

Come funziona la Shell

La Shell è il primo programma che si ha a disposizione dopo essersi "loggati" in Linux. È ciò che sistema un sacco di cose in modo da non caricare il kernel di compiti ripetitivi e permettergli di occuparsi di compiti di più alto livello. Poiché ogni utente ha una sua Shell che si frappone tra lui e Linux, è proprio la Shell a interpretare i comandi digitati e ad esaminarne la sintassi prima di mandarli in esecuzione un pezzo alla volta.

    - Cavolo! Questa cosa di interpretare i comandi non ha niente a vedere con un interprete, vero?

    - In effetti sì. Per la verità, la Shell é un interprete che porta con sé un potente linguaggio dotato di comandi di alto livello ed è capace, come ti mostrerò, di creare collegamenti, di prendere decisioni e di immagazzinare valori all'interno di variabili.

Ti spiegherò i principali compiti che la Shell svolge nell'ordine in cui li esegue. Fa' attenzione a quest'ordine perché è fondamentale per capire tutto ciò che dirò in seguito.

Esame della Riga di Comando

Durante questo esame la Shell identifica i caratteri speciali (riservati) utili all'interpretazione della riga, quindi verifica se la riga immessa è un'assegnazione o un comando.

Assegnazione

Se la Shell trova due campi separati da un segno di uguale (=) senza spazi tra il primo e il secondo, identificherà tale sequenza come un'assegnazione.

Esempi

$ ls linux linux

In questo esempio la Shell ha identificato ls come un programma e linux come un parametro passato al programma ls.

$ valore=1000

In questo caso, poiché non ci sono spazi (notiamo subito che lo spazio è un carattere riservato), la Shell ha identificato un'assegnazione e ha attribuito il valore 1000 alla variabile valore.

Pinguim com placa de dica (em inglês) Non digitare mai:

$ valore = 1000 bash: valore: not found

In questo caso, la Bash ha incontrato la parola valore posta tra spazi e ha interpretato tutto questo come se tu avessi mandato in esecuzione un programma chiamato valore con i parametri = e 1000.

Comando

Quando si digita una riga nel prompt di Linux, essa è suddivisa in segmenti separati da spazi: il primo segmento è il nome del programma (la cui esistenza sarà verificata), quindi si identificano, nell'ordine, opzioni/parametri, redirezionamenti e variabili.

Se il programma identificato esiste, la Shell verifica i permessi dei file interessati (compreso il programma stesso) e restituisce un errore nel caso in cui non si disponga dei permessi per eseguire quell'azione.

Risoluzione dei Redirezionamenti

Dopo aver identificato i componenti della riga che sono stati digitati, la Shell inizia a risolvere i redirezionamenti. Tra i suoi vantaggi la Shell comprende ciò che chiamiamo redirezionamento, il quale può essere di input (stdin), di output (stdout) o di errore (stderr). Più avanti te li spiegherò in dettaglio.

Sostituzione delle Variabili

A questo punto la Shell verifica se le eventuali variabili (parametri che iniziano con $) presenti nel campo del comando sono definite e le sostituisce con i rispettivi valori reali.

Sostituzione dei Metacaratteri

Se nella riga di comando si trova un metacarattere (*, ? ou []), esso sarà sostituito con i suoi possibili valori. Ipotizzando che l'unico file che inizia con la lettera n presente nella directory attuale sia nomechepiùbellononsipuò, se digiti:

$ cd n*

poiché è la Shell a prendersi cura della tua riga e il comando (programma) cd non è stato ancora eseguito, la stessa Shell trasforma n* in nomechepiùbellononsipuò e il comando cd sarà eseguito con successo.

Passare la Riga di Comando al Kernel

Una volta eseguiti i compiti appena illustrati, la Shell monta la riga di comando con tutte le sostituzioni necessarie e invia una chiamata al kernel affinché esegua la riga in una nuova Shell (Shell figlia) non prima di averle assegnato un numero di processo (PID ou Process IDentification). A questo punto la Shell si addormenta e resta inattiva fino al termine del programma. Una volta che il processo si è chiuso (insieme alla Shell figlia), la Shell riprende il controllo e, mostrando il prompt, si rende disponibile a eseguire altri comandi.

Decifrare la Stele di Rosetta

Per scacciare quella sensazione che si prova quando si vede uno script Shell (che sembra piuttosto un ammasso di lettere o un geroglifico), ti mostrerò i più importanti caratteri speciali per farti sentire come Jean-François Champollion quando decifrò la Stele di Rosetta (cerca su "Google" per scoprire chi era, penso che ne valga la pena).

Caratteri per il mascheramento del significato

Quando non vogliamo che la Shell interpreti un carattere speciale, dobbiamo "nasconderlo" alla sua vista. Ciò può essere fatto in tre modi diversi:

Apostrofo (')

Quando la Shell vede una stringa di caratteri tra due apostrofi ('), essa elimina gli apostrofi dalla stringa e non interpreta ciò che sta in mezzo.

$ ls linux* linuxmagazine $ ls 'linux*' bash: linux* no such file or directory

Nel primo caso, la Shell ha "espanso" l'asterisco e ha trovato ed elencato il file linuxmagazine. Nel secondo, gli apostrofi hanno impedito alla Shell di interpretare ciò che racchiudevano, quindi abbiamo ottenuto la risposta che il file linux* non esiste.

Backslash o Barra Rovesciata (\)

È identica all'apostrofo tranne per il fatto che la barra rovesciata inibisce l'interpretazione solo del carattere che la segue.

Immagina di aver accidentalmente creato un file chiamato * (asterisco) –- alcuni tipi di Unix lo permettono -– e di volerlo rimuovere. Se tu pensassi di digitare:

$ rm *

faresti un'enorme stupidaggine, perché il comando rm rimuoverebbe tutti i file della directory corrente. Il modo migliore di rimuovere il file è:

$ rm \*

In questo modo la Shell non interpreterebbe l'asterisco e, di conseguenza, non lo espanderebbe.

Prova a fare questo esperimento scientifico:

$ cd /etc $ echo '*' $ echo \* $ echo *

Hai notato la differenza? Non c'è altro da spiegare.

Virgolette (")

Sono esattamente identiche all'apostrofo tranne per il fatto che, se la stringa tra virgolette contiene un simbolo del dollaro ($), un apice (`), o una barra rovesciata (\), questi caratteri saranno interpretati dalla Shell.

Non ti preoccupare, non ti ho fatto esempi sull'uso delle virgolette perché ancora non conosci il dollaro ($) né l'apice (`). D'ora in poi vedremo nel dettaglio l'uso di questi caratteri speciali. La cosa più importante è capirne il significato.

Caratteri di redirezionamento

La maggior parte dei comandi ha un input, un output e può generare errori. Questo input è chiamato Standard Input o stdin e di default è costituito dalla tastiera. Analogamente, l'output di un comando è chiamato Standard Output o stdout e di default è costituito dallo schermo. Allo schermo è inviato per default anche ogni messaggio di errore proveniente dai comandi, chiamato Standard Error o stderr. Vediamo adesso come modificare questa situazione.

Scriveremo un semplice programmino. Digita:

$ cat

L'istruzione cat elenca il contenuto di un file e lo invia allo Standard Output (stdout). Nel caso in cui l'input non sia definito, essa attende dati da stdin. Poiché non ho specificato l'input, l'istruzione è in attesa di dati dalla tastiera (Standard Input) e, poiché non ho indicato neppure l'output, ciò che digiterò sarà inviato allo schermo (Standard Output). In questo modo ho appena scritto un programmino semplice semplice. Prova anche tu!

Redirezionamento dello Standard Output

Per specificare l'output di un programma usiamo il carattere > (maggiore di) oppure il carattere >> (doppio segno di maggiore) seguito dal nome del file al quale si vuole inviare l'output.

Adesso trasformeremo il semplice programmino di prima in un editor di testi (ma che bravi che siamo!). smile

$ cat > File

L'istruzione cat non ha ancora un input definito, per cui attenderà che i dati in entrata siano immessi tramite tastiera, tuttavia l'output è redirezionato nel file File. In questo modo, tutto ciò che è digitato finisce dritto dritto in File ed ecco pronto l'editor di testo più corto e grezzo del pianeta.

Se digito di nuovo:

$ cat > File

i dati contenuti in File saranno perduti poiché, prima del redirezionamento, la Shell creerà un File vuoto. Per aggiungere dati alla fine del file avrei dovuto digitare:

$ cat >> File

Penguin con un piatto di attenzione Come ti ho già detto prima, la Shell risolve la riga e manda in esecuzione il comando. Quindi, se redirezioni l'output di un file nel file stesso, per prima cosa la Shell "svuota" il file, poi manda in esecuzione il comando. In questo modo hai appena perso il contenuto del tuo amato file.

Notiamo, quindi, che >> (doppio segno di maggiore) serve per accodare del testo in un file.

Redirezionamento dello Standard Error

Poiché il comportamento di default della Shell è ricevere dati dalla tastiera e inviare l'output allo schermo, anche gli errori saranno inviati allo schermo a meno che che tu non indichi dove dovranno essere inviati. Per redirezionare gli errori usa 2> OutputErrore. Nota che tra il numero 2 e il simbolo di maggiore (>) non ci sono spazi.

Penguin con un piatto di attenzione Attento a non confondere >> con 2>. Il primo aggiunge dati in coda in un file, il secondo redireziona lo Standard Error (stderr) in un file ancora da definire. Questa cosa è molto importante!

Supponi che, durante l'esecuzione di uno script, tu possa aver creato (a seconda della direzione presa dal programma) un file chiamato /tmp/magariesiste$$. Per non lasciare roba inutile nel disco rigido, alla fine dello script aggiungerai:

$ rm /tmp/magariesiste$$

Nel caso in cui il file non esista sarà inviato allo schermo un messaggio di errore. Per evitare la comparsa del messaggio si deve aggiungere:

$ rm /tmp/magariesiste$$ 2> /dev/null

Riguardo all'esempio che abbiamo appena visto ho due suggerimenti da darti:

Pinguim com placa de dica (em inglês) Tip # 1

Il simbolo $$ contiene il PID, cioè il numero del processo. Poiché Linux è un sistema multiutente, è bene aggiungere sempre $$ al nome dei file usati dai diversi utenti per evitare problemi di proprietà. Per chiarire meglio, nel caso in cui tu dessi al file semplicemente il nome magariesiste, il primo a usarlo (quindi a crearlo) ne diventerebbe il proprietario e tutti gli altri otterrebbero un messaggio di errore se tentassero di scriverci dentro qualcosa.

Per farti testare lo Standard Error direttamente nel prompt della Shell, ti darò un altro esempio. Digita:

$ ls nonesiste bash: nonesiste no such file or directory $ ls nonesiste 2> filedeglierrori $ $ cat filedeglierrori bash: nonesiste no such file or directory

In questo esempio vediamo che, quando lanciamo ls su nonesiste, otteniamo un messaggio di errore. Dopodiché, una volta redirezionato lo Standard Error in filedeglierrori ed eseguito nuovamente lo stesso comando, otterremo soltanto il prompt. Quando leggiamo il contenuto del file nel quale è stato redirezionato lo Standard Error, vediamo che il messaggio di errore è stato immagazzinato dentro lo stesso file. Fa' la prova anche tu.

Pinguim com placa de dica (em inglês) Tip # 2

    - Che diavolo è /dev/null?

    - In Unix esiste un file fantasma chiamato /dev/null. Tutto ciò che viene inviato in questo file sparisce completamente come in una specie di buco nero. Nel caso dell'esempio, poiché non mi interessava salvare l'eventuale messaggio di errore proveniente da l comando rm, l'ho redirezionato in questo file.

È interessante notare che i caratteri di redirezionamento sono cumulativi. Se nell'esempio precedente digitassimo:

$ ls nonesiste 2>> filedeglierrori

il messaggio di errore proveniente da ls sarebbe aggiunto in coda in filedeglierrori.

Redirezionamento dello Standard Input

Per eseguire il redirezionamento dello Standard Input usiamo il simbolo < (minore di).

    - E questo a che serve? - mi chiederai.

    - Lascia che ti faccia un esempio e capirai al volo.

Supponi di voler inviare una email al tuo capo. Per il capo ci facciamo in quattro, vero? Quindi, invece di scrivere l' email direttamente nel prompt facendo in modo che sia impossibile correggere una frase nella quale, senza volere, hai scritto un bel "dassi", puoi creare un file con il contenuto del messaggio e, dopo aver controllato almeno una dozzina di volte che non ci siano errori, puoi finalmente inviarlo. Per fare tutto questo ti basta digitare:

$ mail capo < fileconemailperilcapo

Il tuo capo riceverà il contenuto di fileconemailperilcapo.

Here Document

Un altro tipo di redirezionamento particolare permesso dalla Shell è chiamato here document. Esso è rappresentato dal simbolo << (doppio segno di minore) e serve per indicare alla Shell che il campo di un comando inizia nella riga seguente e termina quando incontra una riga il cui contenuto è esattamente l'etichetta che segue il simbolo <<.

Dai un'occhiata al seguente frammento di script che contiene una routine ftp:

    ftp -ivn hostremoto << fineftp
        user $Utente $Password
        binary
        get fileremoto
    fineftp

In questo pezzo di programma ci sono un sacco di dettagli interessanti:

  1. Le opzioni che ho usato per ftp (-ivn) servono per far mostrare al programma tutto ciò che accade (—v di verbose) e per fare in modo che non ti chieda se sei sicuro di voler inviare tutti i file (—i di interactive), mentre l'opzione —n si usa per evitare che ftp richieda utente e password poiché queste informazioni saranno indicate tramite un'istruzione specifica (user);
  2. Quando ho usato << fineftp, stavo dicendo all'interprete:
    - Sentimi bene Shell, stattene buona finché non incontri l'etichetta fineftp. Tanto non capiresti niente visto che sono istruzioni specifiche del comando ftp e tu di ftp non capisci niente.
    Se fosse così e basta sarebbe semplice, ma l'esempio stesso ci fa vedere che esistono due variabili ($Utente e $Password), che la Shell risolve prima del redirezionamento. Il grande vantaggio di questo tipo di costrutto è che esso fa in modo che siano interpretati anche i comandi posti all'interno del campo di here document, cosa contraria a quanto ho appena detto. Più avanti ti spiegherò come funziona, per adesso mancano alcuni strumenti.
  3. Il comando user fa parte del repertorio dei comandi di ftp e serve a trasferire l'utente ela password letti una routine precedente a questa porzione di codice e assegnati, rispettivamente, alle variabili $Utente e $Password.
  4. L'istruzione binary appartiene ancora a ftp e serve a indicare che il trasferimento di fileremoto sarà eseguita in modalità binaria, cioè il contenuto del file non sarà interpretato per sapere se è in ASCII, EBCDIC, ...
  5. Il comando get fileremoto dice a ftp di prendere questo file in hostremoto e trasferirlo nel nostro host locale. Se volessimo inviare il file all'host remoto dovremmo usare l'istruzione put.

Penguin con un piatto di attenzione Un errore molto freqüente nell'uso di un' etichetta (come fineftp dell'esempio precedente) è causato dalla presenza di spazi prima o dopo l'etichetta stessa. Presta molta attenzione perché questo tipo di errore è una vera noia da risolvere per i programmatori. Ricorda: un' etichetta che si rispetti avrà una riga tutta per sé.

    - Ho capito, ho capito! So che ho divagato e mi sono buttato sui comandi di ftp lasciando da parte la Shell, ma visto che imparare è sempre una cosa buona e che è raro che ci siano persone disposte a insegnare...

Redirezionamento dei Comandi

I redirezionamenti di cui abbiamo parlato finora si riferiscono sempre a file, cioè inviano a un file, ricevono da un file, simulano un file locale e così via. Ciò che vedremo tra poco redireziona l'output di un comando nell'input di un altro. Ciò è utilissimo e risolve un sacco di problemi. Il suo nome è pipe (che in inglese significa tubo, poiché incanala l'output di un comando nell'input di un altro) e il suo simbolo è una barra verticale (|).

$ ls | wc -l     21

Il comando ls ha passato la lista dei file al comando wc il quale, grazie all'opzione –l , conta il numero di righe ricevute. In questo modo si può affermare categoricamente che nella mia directory ci sono 21 file.

$ cat /etc/passwd |sort | lp

Questa riga di comando invia il listato del file /etc/passwd all'input del comando comando sort, il quale lo classifica e lo invia a lp che è il gestore dello spool di stampa.

Caratteri di Ambiente

Quando vuoi dare priorità a una frase la scrivi tra parentesi, giusto? In effetti, è normale pensarla così a causa della matematica. All'interno della Shell, invece, per dare la priorità a un elemento non si le usano le parentesi ma gli apici (`) . Eccoti un esempio di come si utilizzano

Voglio sapere quanto utenti sono "loggati" nel computer che amministro. Posso digitare:

$ who | wc -l     8

Il comando who passa il listato degli utenti connessi al comando wc –l il quale conta quante righe ha ricevuto e visualizza la risposta sullo schermo. Tuttavia, invece di ottenere un otto tutto solo in mezzo allo schermo, voglio che esso compaia all'interno di una frase.

Per visualizzare frasi sullo schermo si usa il comando echo. Vediamo cosa succede in questo modo:

$ echo "Ci sono who | wc -l utenti connessi" Ci sono who | wc -l utenti connessi

Ha ha!! Non ha funzionato! Non ha funzionato per niente e non a causa delle virgolette che ho messo, ma perché avrei dovuto eseguire who | wc -l prima di echo. Per risolvere il problema devo dare la priorità alla seconda parte del comando per mezzo degli apici:

$ echo "Ci sono `who | wc -l` utenti connessi" Ci sono 8 utenti connessi

Per eliminare tutti quegli spazi prima dell' 8 generato da wc -l, è sufficiente togliere le virgolette:

$ echo Ci sono `who | wc -l` utenti connessi Ci sono 8 utenti connessi

Come ti ho già detto prima, le virgolette impediscono alla Shell di interpretare tutto ciò che si trova al loro interno. Poiché alla Shell serve un solo spazio come separatore, tutti gli spazi saranno sostituiti da uno solo di essi una volta eliminate le virgolette.

Prima di parlarti delle parentesi lasciami dire due paroline sull'uso del punto-e-virgola (;). All'interno della Shell si deve sempre immettere un comando per riga. Se vuoi raggruppare più comandi nella stessa riga, devi separarli con un punto-e-virgola:

$ pwd ; cd /etc; pwd; cd -; pwd /home/miadirectory /etc/ /home/miadirectory

In questo esempio, ho visualizzato il nome della directory corrente con il comando pwd, mi sono spostato nella directory /etc, ho nuovamente visualizzato il nome della directory e sono tornato nella directory in cui mi trovavo in precedenza (cd -) visualizzandone il nome. Nota che ho messo il punto-e-virgola (;) in ogni posizione possibile per far vedere che non è importante che ci siano spazi prima o dopo di esso.

Vediamo adesso il caso delle parentesi. Osserva bene questo esempio molto simile al precedente:

$ (pwd ; cd /etc ; pwd;) /home/miadirectory /etc/ $ pwd /home/miadirectory

    - E adesso che cavolo succede? Ero in /home/miadirectory, mi sono spostato in /etc, ho constatato che mi trovavo al suo interno con pwd e, una volta terminata la sequenza dei comandi, mi sono accorto di essere ancora in /home/miadirectory, come se non ne fossi mai uscito!

    - Eh! Ci sarà mica il trucco?

    - Mi prendi in giro? Nessun trucco! L'aspetto interessante delle parentesi è che esse invocano una nuova Shell per eseguire i comandi che si trovano al loro interno. Seguendo l'ultimo esempio, ci siamo spostati davvero nella directory /etc, ma una volta eseguiti i comandi all'interno delle parentesi, la nuova Shell aperta nella directory /etc è stata chiusa e siamo tornati alla Shell precedente la cui directory era /home/miadirectory. Fa' altre prove con cd e ls per capire bene il funzionamento delle parentesi.

Ora che abbiamo imparato questi concetti, vediamo un altro esempio:

$ mail assistenza << FINE > Salve a tutti, oggi alle ‘date "+%H:%M"‘ > si è ripresentato il problema > che vi avevo illustrato per > telefono. A seguito della vostra richiesta > vi invio la lista dei file > della directory: > ‘ls -l‘ > Cordiali saluti. > FINE

Finalmente siamo in grado di mostrare ciò di cui abbiamo parlato riguardo a here document. Ai comandi tra apici (`) sarà data la priorità, per cui la Shell li eseguirà prima del comando mail. Quando l'assistenza riceverà l' e-mail, vedrà che i comandi date e ls sono stati eseguiti subito prima del comando mail, ricevendo così un'istantanea dell'ambiente nel momento in cui il messaggio è stato inviato.

Il prompt di default primario della Shell è, come abbiamo visto, il dollaro ($). Tuttavia, la Shell usa il concetto di prompt secondario, detto di continuazione del comando, il quale viene mostrato sullo schermo quando si verifica un'interruzione della riga e l'istruzione non è terminata. Questo prompt è rappresentato dal simbolo di maggiore (>), visibile nell'esempio a partire dalla 2ª riga dell'esempio.

Per concludere e incasinare tutto devo dirti che esiste un costrutto più moderno utilizzato regolarmente per dare priorità all'esecuzione di comandi, esattamente come l'uso degli apici (`). Il costrutto è di tipo $(cmd), in cui cmd è costituito da uno o più comandi che hanno priorità di esecuzione all'interno del loro contesto.

Stando così le cose, gli apici (`) e i costrutti di tipo $(cmd) hanno lo stesso scopo. Tuttavia, a chi lavora con sistemi operativi di fornitori diversi (multipiattaforma) consiglio l'uso degli apici poiché il comando $(cmd) non è stato portato in tutti i tipi di Shell. Tra di noi, qui al Bar, userò entrambe le forme senza distinzione.

Riesaminiamo l'esempio sugli apici da questo nuovo punto di vista:

$ echo Ci sono $(who | wc -l) utenti connessi Ci sono 8 utenti connessi

Adesso osserva:

$ File=ls $ echo $File ls

In questo esempio ho compiuto un'assegnazione (=) ed eseguito un'istruzione. Ciò che volevo era che la variabile $File ricevesse l'output del comando ls. Poiché le istruzioni all'interno di uno script sono interpretate dall'alto verso il basso e da sinistra verso destra, l'assegnazione è stata fatta prima dell'esecuzione di ls. Per fare ciò che voglio è necessario che dia priorità di esecuzione a questo comando a discapito dell'assegnazione e ciò può essere fatto in uno qualsiasi dei modi seguenti:

$ File=`ls`

oppure:

$ File=$(ls)

Per terminare l'argomento vediamo un ultimo esempio. Supponiamo che io voglia inserire nella variabile $File l'elenco in forma lunga (ls -l) di tutti i file che iniziano con file seguito da un solo carattere (?). Digiterò:

$ File=$(ls -l file?)

oppure:

$ File=`ls -l file?`

Ma se provo a digitare:

$ echo $File -rw-r--r-- 1 jneves jneves 19 May 24 19:41 file1 -rw-r--r-- 1 jneves jneves 23 May 24 19:43 file2 -rw-r--r-- 1 jneves jneves 1866 Jan 22 2003 filel

    - Accidenti, guarda che pasticcio!

    - Certo, te l'ho detto, se lasci che la Shell “veda” gli spazi, ogni volta li sostituirà tutti con un unico spazio. Per fare in modo che l'elenco abbia un aspetto decente è necessario impedire alla Shell di interpretare la variabile:

$ echo "$File" -rw-r--r-- 1 jneves jneves 19 May 24 19:41 file1 -rw-r--r-- 1 jneves jneves 23 May 24 19:43 file2 -rw-r--r-- 1 jneves jneves 1866 Jan 22 2003 filel

    - Amico mio, fa' pratica con questi esempi: la prossima volta che ci vediamo ti spiegherò una serie di istruzioni tipiche della programmazione Shell. Ciao! Ah! Un'ultima cosa. Nella Shell, il cancelletto (#) si usa quando vogliamo lasciare un commento.

$ exit # chiedi il conto al cameriere frown

Licença Creative Commons - Atribuição e Não Comercial (CC) 2017 Pelos Frequentadores do Bar do Júlio Neves.
Todo o conteúdo desta página pode ser utilizado segundo os termos da Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença.