리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기

Ambiente di testFamiglia RHELAlmaLinux 9.8bash 5.1account root
Shell$1$#--

Gli argomenti della riga di comando di Linux (command-line argument) sono i valori che si passano a un programma scrivendoli dopo il nome del comando, separati da spazi. Passando opzioni, virgolette, caratteri jolly e -- a uno script di prova che stampa così come sono gli argomenti ricevuti su un server AlmaLinux 9, abbiamo visto che a dividere gli argomenti era la shell e a leggere le opzioni era ciascun comando.

L'output qui sotto è esattamente quello ottenuto con bash 5.1 nell'account root di un server AlmaLinux 9.8. Gli script di prova e i file di esempio sono stati creati in una cartella di lavoro separata, e il percorso /home/user/www è un valore di esempio.

1️⃣ Cosa sono gli argomenti della riga di comando di Linux?

Se sulla riga di comando scrivi qualcosa come [comando arg1 arg2], la shell divide le parole in base agli spazi. La prima parola diventa il programma da eseguire, e le altre vengono passate in ordine a quel programma come suoi argomenti.

Per vedere gli argomenti passati abbiamo creato args.sh nella cartella di lavoro. $0 contiene il nome con cui è stato eseguito, $# il numero di argomenti e da $1 in poi gli argomenti in ordine. Le parentesi quadre servono a mostrare dove inizia e finisce ogni argomento.

#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
  echo "\$$i = [$a]"
  i=$((i+1))
done

Abbiamo dato allo script il permesso di esecuzione e lo abbiamo eseguito con tre parole: a, b e c.

./args.sh a b c
$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]

Le tre parole sono finite in $1, $2 e $3, e $# valeva 3. Se esegui lo script scrivendone il nome dopo bash, $0 contiene il nome esattamente come scritto, args.sh.

bash args.sh a b c
$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]

Solo $0 è cambiato in args.sh; i tre argomenti e il loro numero sono rimasti uguali a prima.

2️⃣ Argomenti della riga di comando e opzioni dei comandi

I comandi Linux si scrivono di solito nell'ordine [comando -opzione argomento]. Le opzioni cambiano il modo in cui il comando agisce, e gli argomenti indicano i file, i percorsi o i valori su cui lavora.

ls -l /home/user/www

Per la shell anche -l è solo un argomento. Passando le stesse parole ad args.sh, -l è finito in $1 e il percorso in $2.

./args.sh -l /home/user/www
$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]

A leggere -l come opzione è ls. Per questo la stessa lettera ha significati diversi nei vari comandi: -n di head stabilisce quante righe stampare, mentre -n di ls mostra il proprietario come numero invece che come nome.

Alcune opzioni prendono come proprio valore la parola che le segue subito. Nel comando find, -type usa f e -name usa "*.txt" come valore; un valore legato così a un'opzione si chiama argomento dell'opzione.

find . -type f -name "*.txt"

In questo comando il . iniziale è un argomento non legato ad alcuna opzione e indica la cartella da cui parte la ricerca.

3️⃣ Formati delle opzioni dei comandi Linux

Le opzioni brevi iniziano con un solo trattino, sono di una lettera e se ne possono scrivere più di una attaccate. Per prima cosa abbiamo elencato la cartella site della cartella di lavoro con [ls -l -a].

ls -l -a site
total 8
drwxr-xr-x 3 root root  52 Oct 28 16:00 .
drwxr-xr-x 3 root root 137 Oct 29 01:20 ..
-rw-r--r-- 1 root root  17 Oct 28 16:00 .htaccess
drwxr-xr-x 2 root root  23 Oct 28 16:00 css
-rw-r--r-- 1 root root  14 Oct 28 16:00 index.html

Poi l'abbiamo confrontata con diff con l'output di [ls -la], che unisce le due lettere.

diff <(ls -l -a site) <(ls -la site) && echo same
same

I due output non differivano di un solo carattere. Le opzioni lunghe iniziano con due trattini e si scrivono come parole; --all di ls è la stessa opzione di -a, quindi anche [ls -l --all site] ha dato lo stesso risultato.

Le opzioni lunghe vengono accettate anche se ne scrivi solo l'inizio, purché corrisponda a una sola opzione. --al corrispondeva a due opzioni, --all e --almost-all, quindi ls non ha stampato l'elenco ed è terminato con codice di uscita 2.

ls --al site
ls: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.

Le opzioni che ricevono un valore si possono scrivere in più forme. Stampando le prime due righe di a.txt con head, l'opzione breve può avere il valore attaccato, come [-n2].

head -n2 a.txt
alpha
beta

L'opzione lunga unisce il valore con un segno di uguale, come [--lines=2].

head --lines=2 a.txt
alpha
beta

Tutte e quattro le forme, comprese [-n 2] e [--lines 2] separate da uno spazio, hanno stampato le due righe alpha e beta.

ls, head e cat leggono le opzioni con la funzione getopt_long della libreria C. Esaminando i tre file di programma con strings, tutti contenevano il nome di questa funzione.

Per verificare le stesse regole dalla shell si usa il comando getopt di util-linux. Dopo -o si scrivono le opzioni brevi e dopo -l quelle lunghe; i due punti dopo una lettera indicano che l'opzione riceve un valore.

getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt
 -l -a -n '2' --all -- 'a.txt'

Il -la scritto attaccato è stato diviso in -l e -a, e -n 2 è stato raggruppato come -n con il valore 2. a.txt, che non è un'opzione, è stato spostato in fondo, dopo --.

4️⃣ Argomenti tra virgolette e caratteri jolly

Un nome di file che contiene uno spazio va racchiuso tra virgolette per essere passato come un solo argomento.

./args.sh "my file.txt" report.txt
$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]

Senza virgolette, my e file.txt sono stati separati e $# è diventato 3. Se lo passi così a ls o cat, cercheranno due file chiamati my e file.txt.

./args.sh my file.txt report.txt
$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]

I caratteri jolly vengono sostituiti dalla shell con i nomi dei file prima che il programma li riceva. Passando *.txt nella cartella di lavoro, sono arrivati in ordine di nome i quattro file che finiscono con .txt.

./args.sh *.txt
$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]

Il "*.txt" tra virgolette non è stato sostituito dalla shell ed è diventato un solo argomento, carattere per carattere. Per opzioni come -name di find, in cui è il programma a confrontare il modello, lo si passa così, tra virgolette.

./args.sh "*.txt"
$0 = ./args.sh
$# = 1
$1 = [*.txt]

Anche le virgolette vuote vengono passate come un argomento vuoto. Eseguendo [./args.sh '' b], $# valeva 2 e $1 era vuoto.

5️⃣ Fine delle opzioni del comando (--)

Un argomento che inizia con un trattino, come un file chiamato -n, viene letto dal comando come un'opzione. Eseguendo [ls -n] nella cartella dash, che contiene solo quel file, ls ha preso -n non come nome di file ma come opzione di output numerico e ha elencato la cartella.

ls -n
total 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -n

Gli argomenti scritti dopo -- non vengono letti come opzioni, anche se iniziano con un trattino. [ls -- -n] ha stampato solo il nome di file -n.

ls -- -n
-n

All'interno di uno stesso comando, gli stessi caratteri vengono letti in modo diverso prima e dopo --. Passando -n due volte a cat, il primo -n è stato letto come opzione dei numeri di riga e il -n dopo -- come nome di file, e il contenuto del file è uscito con i numeri di riga.

cat -n -- -n
     1	dash file

Si può anche aggiungere il percorso e scrivere ./-n; in questo caso l'argomento non inizia con un trattino e viene letto come lo stesso file -n.

Leggere -- come fine delle opzioni è anch'essa una regola del comando. Passandolo ad args.sh, che non legge opzioni, anche -- è finito così com'è in $1.

./args.sh -- -a
$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]

Le convenzioni delle utility POSIX stabiliscono che il primo -- che non sia un argomento di opzione venga accettato come fine delle opzioni. Per questo, con i comandi che seguono queste convenzioni, i nomi di file che iniziano con - si scrivono dopo --.

6️⃣ Ricevere gli argomenti della riga di comando in uno script di shell

Uno script di shell legge gli argomenti ricevuti tramite parametri posizionali e parametri speciali. Anche il main(int argc, char *argv[]) di un programma C riceve gli stessi argomenti; messi uno accanto all'altro, appaiono così.

ParametroValore contenutoFunzione main del C
$0Nome dello script eseguitoargv[0]
$1 ~ $9Dal primo al nono argomentoargv[1] ~ argv[9]
${10}Dal decimo argomento in poi, tra parentesi graffeargv[10]
$#Numero di argomenti, $0 esclusoargc - 1
"$@"Tutti gli argomenti, ciascuno separatoDa argv[1] fino alla fine
"$*"Tutti gli argomenti uniti in uno con spazi—

Un programma Python riceve gli stessi argomenti come lista sys.argv. Passando tre argomenti con [python3 -c], my file.txt tra virgolette è finito in un solo elemento della lista, e nel primo elemento c'era -c.

python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l
['-c', 'a', 'my file.txt', '-l']

"$@" e "$*" danno risultati diversi quando sono racchiusi tra virgolette doppie. Per vedere la differenza abbiamo creato star.sh, che stampa le due forme una dopo l'altra.

#!/bin/bash
echo 'with "$@"'
printf '  [%s]\n' "$@"
echo 'with "$*"'
printf '  [%s]\n' "$*"

Abbiamo eseguito star.sh con tre argomenti: a, "b c" e d.

./star.sh a "b c" d
with "$@"
  [a]
  [b c]
  [d]
with "$*"
  [a b c d]

"$@" ha passato i tre argomenti separatamente, mentre "$*" li ha uniti con spazi e passati come uno solo.

Per questo, quando si passano a un altro comando gli argomenti ricevuti senza modificarli, si usa "$@".

shift scarta $1 e sposta in avanti di una posizione gli argomenti rimanenti. Si usa negli script che leggono prima un'opzione e trattano il resto come elenco di file.

Abbiamo creato shift.sh, che stampa $1 e $# prima e dopo shift.

#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift:  \$1 = $1, \$# = $#"

Abbiamo eseguito shift.sh con tre argomenti: -v, a.txt e b.txt.

./shift.sh -v a.txt b.txt
before shift: $1 = -v, $# = 3
after shift:  $1 = a.txt, $# = 2

Dal decimo argomento in poi il numero va racchiuso tra parentesi graffe, come ${10}. Abbiamo creato ten.sh, che stampa $10 e ${10} uno accanto all'altro.

#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"

Abbiamo passato a ten.sh 11 argomenti, da a a k.

./ten.sh a b c d e f g h i j k
$10 = a0
${10} = j

$10 è uscito come a0, cioè $1 seguito da uno 0, mentre ${10} è uscito come decimo argomento, j.

🔲 Simulatore di argomenti della riga di comando

Nel simulatore qui sotto puoi passare virgolette, caratteri jolly e -- ad args.sh, e anche digitare tu stesso i comandi per vedere come ls e getopt leggono le opzioni e come star.sh e shift.sh ricevono gli argomenti.

Simulatore di argomenti della riga di comandobash 5.1
[root@server work]#
È un server AlmaLinux virtuale che funziona solo nel tuo browser; args.sh stampa gli argomenti ricevuti con il loro numero, e ↑↓ richiama i comandi usati prima.

🔢 FAQ & contenuti consigliati

Il limite della lunghezza complessiva di argomenti e variabili d'ambiente si controlla con [getconf ARG_MAX]; sul server AlmaLinux 9.8 era di 2097152 byte. Oltre questo limite il programma non viene eseguito e compare l'errore [Argument list too long]. Quando i file sono moltissimi, non passarli tutti insieme con un carattere jolly, ma dividili con -exec di find o con xargs.

Un argomento (argument) è il valore effettivamente passato quando si esegue un comando, mentre un parametro (parameter) è il nome con cui il lato che riceve ottiene quel valore. In uno script di shell, i parametri posizionali come $1 e $2 ricevono gli argomenti passati.

getopts, integrato in bash, legge una alla volta le opzioni brevi come -v. Non legge le opzioni lunghe, quindi per accettare anche opzioni lunghe come --verbose, riordina prima gli argomenti con il comando getopt usato sopra.

ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Dimostra di essere umano: 0   +   4   =