Tracce
/
Bash
Bash
/
Programma
/
Comandi e argomenti
Co

Comandi e argomenti in Bash

{one: "1 esercizio", many: "%{count} esercizi", other: "%{count} esercizi"}

Informazioni su Comandi e argomenti

Le shell

Una shell è un programma che permette di inserire comandi per interagire con il sistema operativo. Le shell possono essere grafiche: l'ambiente desktop che usi con il mouse o il trackpad è una shell. Ci concentreremo sulle interfacce a riga di comando, dove digiti i comandi e i risultati vengono (di solito) stampati nel terminale.

Esistono molte shell a riga di comando diverse. Windows offre cmd e powershell. Mac e Linux offrono le «Unix shell», e ce ne sono molte. La shell predefinita su Mac è zsh. csh è una shell legacy con una sintassi simile a quella del C. bash è una delle shell più diffuse, soprattutto su Linux.

Una delle prime shell in assoluto è la Bourne shell, sh. Con il tempo, questa shell è stata standardizzata per essere fornita su ogni sistema di tipo Unix. Molte shell derivano dalla Bourne shell e spesso aggiungono funzionalità interattive o di programmazione.

Bash deriva dalla Bourne shell. Per questo è chiamata «Bourne-again shell». È la shell predefinita su molti sistemi Linux. Bash offre molte funzionalità che la rendono una shell interattiva piacevole da usare, tra cui:

  • un prompt completamente personalizzabile,
  • la possibilità di richiamare e modificare i comandi dalla cronologia,
  • la possibilità di gestire i processi in esecuzione,
  • alias che riducono la digitazione,
  • e altro ancora.

Questo track non riguarda come usare bash come shell interattiva. Riguarda invece imparare a scrivere programmi usando bash. L'accento sarà posto sull'uso del solo bash per risolvere i problemi, anche se non ci sono restrizioni nel richiamare strumenti esterni.

Fondamenti di bash: comandi e argomenti

Bash legge i comandi dal suo input (che di solito è un terminale o un file). Ogni riga di input che legge viene trattata come un comando: un'istruzione da eseguire. (Esistono alcuni casi avanzati, come i comandi che si estendono su più righe, di cui parleremo più avanti.)

Bash divide ogni riga in parole delimitate da un carattere di spaziatura (spazi e tabulazioni). La prima parola della riga è il nome del comando da eseguire. Tutte le parole rimanenti diventano argomenti di quel comando (opzioni, nomi di file e così via).

Note

Negli esempi che seguono ti mostreremo alcuni comandi interattivi che puoi eseguire.

  • Il carattere # avvia un commento. Le parole che seguono il commento vengono ignorate dalla shell; il commento serve solo a chi legge.
  • Il carattere $ indica il prompt della shell. Se stai copiando il comando, non includere il prompt.
# Note: It is always a good idea to run `ls` before `rm`
# to make sure you know what you are deleting.

$ rm *            # Remove all files in the current directory.
                  # Make sure you run this in a temp directory or you can lose files!
$ ls              # List files in the current directory (no output, no files).
$ touch a   b c   # Create files 'a', 'b' and 'c'.
$ ls              # List files again; this time the outputs: 'a', 'b' and 'c'.
a  b  c

rm è un'applicazione che elimina i file che le vengono passati. * è un carattere glob, un pattern «wildcard» che corrisponde a tutti i file nella directory corrente. Parleremo più in dettaglio dei glob più avanti.

Hai notato che ci sono diversi spazi tra a e b, e solo uno tra b e c? La quantità di spaziatura tra gli argomenti non ha importanza! Per esempio:

$ echo This is a test.
This is a test.
$ echo This    is    a    test.
This is a test.

echo è un comando che stampa i suoi argomenti sullo standard output (che nel nostro caso è il terminale). Bash divide il comando in cinque parole e invoca il comando echo con quattro argomenti. Gli spazi in più nel secondo esempio non fanno alcuna differenza. echo non sa come erano distribuiti gli spazi tra le parole in origine.

Se vogliamo mantenere la spaziatura in più, dobbiamo passare la frase come un unico argomento. Possiamo farlo usando le virgolette:

$ echo "This    is    a    test."
This    is    a    test.

Le virgolette raggruppano tutto ciò che contengono in un unico argomento. L'argomento è This is a test., spazi specifici inclusi. Nota che le virgolette non fanno parte dell'argomento: bash le rimuove prima di passare quell'unico argomento a echo.

Gli argomenti sono separati dal nome del comando e l'uno dall'altro da uno spazio. È importante ricordarlo. Per esempio, il seguente è sbagliato:

$ [-f file]
bash: [-f: command not found

L'intenzione è verificare l'esistenza di un file chiamato file. È ragionevole pensare che la spaziatura intorno a [ e ] non conti, ma [ è in realtà un comando e richiede che il suo ultimo argomento sia ]. (Tratteremo il comando [ più in dettaglio più avanti.) Quindi dobbiamo separare [ da -f e ] da file. Altrimenti bash penserà che stiamo cercando di eseguire un comando chiamato [-f con un unico argomento file]. Il comando corretto separa tutti gli argomenti con uno spazio:

$ [ -f file ]

(Vediamo molte persone confuse da questo comportamento: pensano che [...] sia «solo sintassi» e che si possano omettere gli spazi; [ è un comando e la spaziatura è obbligatoria.)

Se il nome del file contiene spazi o altri caratteri speciali, va messo tra virgolette anche lui:

$ [ -f "my file" ]

Tipi di comandi

Bash riconosce diversi tipi di comandi: alias, funzioni, builtin, keyword ed eseguibili. Sono tutti comandi e si comportano tutti in modo molto simile.

Per impostazione predefinita gli alias sono abilitati solo nelle shell interattive, non negli script di shell. Non li tratteremo qui.

Funzioni

Una funzione contiene comandi di shell e si comporta in modo molto simile a un piccolo script; può persino accettare argomenti e creare variabili locali. Quando una funzione viene chiamata, i comandi al suo interno vengono eseguiti. Le funzioni saranno trattate in modo approfondito più avanti.

Builtin

Bash ha alcuni comandi di base integrati, come: cd (cambia directory), echo (scrive sull'output) e così via. Si possono considerare come funzioni già fornite.

Keyword

Le keyword sono simili ai builtin, con la differenza principale che le keyword sono a tutti gli effetti sintassi di bash e possono essere analizzate con regole speciali. Per esempio, [ è un builtin di bash, mentre [[ è una keyword di bash; entrambi servono a verificare diverse condizioni. Ma la keyword [[ ha qualche funzionalità in più. Per esempio, fornisce l'operatore =~ che esegue il controllo con espressioni regolari.

$ [[ "hello world" =~ e.*o ]]   # returns a "success" status
$ [ "hello world" =~ e.*o ]
bash: [: =~: binary operator expected

Gli operatori di confronto tra stringhe < e > sono un altro esempio di come le keyword analizzino il codice in modo diverso. All'interno di [[...]], questi operatori non richiedono alcuna accortezza particolare.

$ if [[ "$USER" < "n" ]]; then
    echo "$USER is in the first half of the alphabet"
fi
# => glennj is in the first half of the alphabet

Ma all'interno di [...] devi metterli tra virgolette o fare l'escape per evitare che la shell li interpreti come operatori di ridirezione.

$ if [ "$USER" < "n" ]; then
    echo "$USER is in the first half of the alphabet"
fi
# => bash: n: No such file or directory

$ if [ "$USER" \< "n" ]; then
    echo "$USER is in the first half of the alphabet"
fi
# => glennj is in the first half of the alphabet

Eseguibili

L'ultimo tipo di comando che bash può eseguire è un eseguibile. Sono file eseguibili (programmi) presenti nel filesystem del tuo computer che puoi eseguire. (Gli eseguibili possono anche essere chiamati comandi esterni o applicazioni.) Di solito gli eseguibili si richiamano digitando solo il loro nome; il percorso completo del file in genere non è necessario. Questo è possibile perché bash usa una variabile predefinita che lo aiuta a trovare la posizione dei file eseguibili più comuni. Questa variabile si chiama PATH. È un insieme di nomi di directory separati da due punti (per esempio /usr/bin:/bin). Quando viene specificato un comando (per esempio myprogram o ls) senza un percorso di file (e non è un alias, una funzione, un builtin o una keyword), bash cerca nelle directory elencate in PATH. Le directory vengono esaminate in ordine, da sinistra a destra, per vedere se contengono un eseguibile con il nome indicato.

Se l'eseguibile è al di fuori di un percorso noto, sarà necessario specificare il percorso del file dell'eseguibile. Per l'eseguibile myprogram nella directory corrente, usa ./myprogram; se si trova nella directory /opt/somedirectory, usa /opt/somedirectory/myprogram.

Suggerimento: il comando type può essere usato per ottenere dettagli su un comando:

$ type rm
rm is hashed (/bin/rm)
# or it might return: `rm is /bin/rm`

$ type cd
cd is a shell builtin

Script

Uno script è una sequenza di comandi memorizzata in un file. Bash legge il file ed elabora i comandi in ordine. Passa al comando successivo solo quando quello corrente è terminato. L'eccezione è se un comando è stato specificato per essere eseguito in modo asincrono (in background). Non preoccuparti troppo di questo caso per ora; più avanti vedremo come funziona.

Qualsiasi esempio di riga di comando in questa guida può essere usato anche in uno script.

Creare uno script è facile. Inizia creando un nuovo file e inserisci questo sulla prima riga:

#!/bin/bash

Questa riga si chiama direttiva dell'interprete (è anche chiamata hashbang o shebang). Specifica che /bin/bash deve essere usato come interprete quando il file viene usato come eseguibile in un comando. Quando il kernel del sistema operativo esegue un file non binario, legge la prima riga del file. Se la riga inizia con #!, il kernel usa quella riga per determinare l'interprete a cui passare il file. (Esistono anche altri modi validi per farlo, vedi più avanti.) Il #! deve trovarsi all'inizio assoluto del file, senza spazi né righe vuote prima. I comandi del nostro script appariranno su righe separate sotto questa.

Suggerimento: al posto di #!/bin/bash, potresti usare

#!/usr/bin/env bash

env cerca in $PATH l'eseguibile indicato dal suo primo argomento (in questo caso, «bash»). Per una spiegazione più dettagliata di questa tecnica e di come differisce dal semplice #!/bin/bash, vedi questa domanda su StackOverflow.

Non lasciarti ingannare da script o esempi su Internet che usano /bin/sh come interprete. sh non è bash! Bash stesso è una shell «compatibile con sh», il che significa che può eseguire la maggior parte degli script sh e ne conserva gran parte della sintassi. Tuttavia non vale il contrario; alcune funzionalità di bash si rompono o causano comportamenti inattesi in sh. In realtà non esiste un'unica shell sh. Esistono molte implementazioni di shell che supportano la sintassi POSIX-sh. A seconda del tuo sistema operativo, quando esegui sh potresti in realtà stare eseguendo bash, ash, dash o un'altra shell.

Una volta creato il file dello script, lo si può eseguire così:

$ bash myscript

In questo esempio eseguiamo il comando bash e gli diciamo di leggere lo script che abbiamo passato come argomento. Quando lo facciamo in questo modo, la riga #! è solo un commento.

In alternativa, possiamo dare ai nostri script i permessi di esecuzione. Con questo metodo possiamo eseguire lo script come qualsiasi altro eseguibile, senza chiamare bash manualmente:

$ chmod +x myscript  # Mark the file as executable.
$ ./myscript         # Now, myscript can be executed directly
                     # instead of having to specify bash.

Quando eseguiamo il comando in questo modo, il sistema operativo (OS) usa la riga #! per determinare quale interprete usare per eseguire il tuo script.

Crediti

Il contenuto di questa lezione è tratto da Comandi e argomenti della Bash Guide.

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda