리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기
Les arguments de ligne de commande Linux (command-line argument) sont les valeurs que l'on transmet à un programme en les écrivant après le nom de la commande, séparées par des espaces. En passant des options, des guillemets, des jokers et -- à un script de test qui affiche tels quels les arguments reçus sur un serveur AlmaLinux 9, on a vu que le découpage des arguments était fait par le shell, et la lecture des options par chaque commande.
La sortie ci-dessous est exactement celle obtenue avec bash 5.1 sous le compte root d'un serveur AlmaLinux 9.8. Les scripts de test et les fichiers d'exemple ont été créés dans un dossier de travail à part, et le chemin /home/user/www est une valeur d'exemple.
1️⃣ Qu'est-ce qu'un argument de ligne de commande Linux ?
Quand on écrit sur la ligne de commande quelque chose comme [commande arg1 arg2], le shell découpe les mots aux espaces. Le premier mot devient le programme à exécuter, et les autres mots lui sont passés dans l'ordre comme arguments.
Pour voir les arguments transmis, nous avons créé args.sh dans le dossier de travail. $0 contient le nom utilisé pour le lancer, $# le nombre d'arguments, et à partir de $1 les arguments dans l'ordre. Les crochets montrent où chaque argument commence et se termine.
#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
echo "\$$i = [$a]"
i=$((i+1))
doneNous avons donné au script le droit d'exécution, puis l'avons lancé avec trois mots : a, b et c.
./args.sh a b c$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Les trois mots sont allés dans $1, $2 et $3, et $# valait 3. Si l'on lance le script en écrivant son nom après bash, $0 contient le nom tel qu'il a été écrit, args.sh.
bash args.sh a b c$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Seul $0 est devenu args.sh ; les trois arguments et leur nombre étaient les mêmes qu'avant.
2️⃣ Arguments de ligne de commande et options de commande
Les commandes Linux s'écrivent en général dans l'ordre [commande -option argument]. Les options changent la façon dont la commande agit, et les arguments indiquent les fichiers, chemins ou valeurs qu'elle traite.
ls -l /home/user/wwwPour le shell, -l n'est qu'un argument de plus. En passant les mêmes mots à args.sh, -l est allé dans $1 et le chemin dans $2.
./args.sh -l /home/user/www$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]C'est ls qui lit -l comme une option. C'est pourquoi une même lettre n'a pas le même sens d'une commande à l'autre : -n de head fixe le nombre de lignes affichées, tandis que -n de ls affiche le propriétaire sous forme de numéro au lieu du nom.
Certaines options prennent comme valeur le mot qui les suit immédiatement. Dans la commande find, -type prend f et -name prend "*.txt" comme valeur ; une valeur rattachée ainsi à une option s'appelle un argument d'option.
find . -type f -name "*.txt"Dans cette commande, le . du début est un argument rattaché à aucune option, qui indique le dossier où commence la recherche.
3️⃣ Formats des options de commande Linux
Les options courtes commencent par un seul tiret, tiennent en une lettre et peuvent s'écrire collées. Nous avons d'abord affiché le dossier site du dossier de travail avec [ls -l -a].
ls -l -a sitetotal 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.htmlNous l'avons ensuite comparé avec diff à la sortie de [ls -la], qui colle les deux lettres.
diff <(ls -l -a site) <(ls -la site) && echo samesameLes deux sorties ne différaient pas d'un seul caractère. Les options longues commencent par deux tirets et s'écrivent en mots ; --all de ls est la même option que -a, donc [ls -l --all site] a donné le même résultat.
Une option longue est acceptée même si l'on n'en écrit que le début, à condition qu'il ne corresponde qu'à une seule option. --al correspondait à deux options, --all et --almost-all, si bien que ls n'a affiché aucune liste et s'est terminé avec le code de sortie 2.
ls --al sitels: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.Une option qui prend une valeur peut s'écrire de plusieurs façons. Pour afficher les deux premières lignes de a.txt avec head, l'option courte peut avoir sa valeur collée, comme [-n2].
head -n2 a.txtalpha
betaL'option longue relie sa valeur par un signe égal, comme [--lines=2].
head --lines=2 a.txtalpha
betaLes quatre formes, y compris [-n 2] et [--lines 2] avec un espace, ont affiché les deux lignes alpha et beta.
ls, head et cat lisent leurs options avec la fonction getopt_long de la bibliothèque C. En examinant les trois fichiers de programme avec strings, on retrouvait ce nom de fonction dans chacun.
Pour vérifier les mêmes règles depuis le shell, on utilise la commande getopt de util-linux. Les options courtes s'écrivent après -o et les longues après -l ; un deux-points après une lettre signifie que l'option prend une valeur.
getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt -l -a -n '2' --all -- 'a.txt'Le -la collé a été séparé en -l et -a, et -n 2 a été regroupé en -n avec la valeur 2. a.txt, qui n'est pas une option, a été déplacé à la fin, après --.
4️⃣ Arguments entre guillemets et jokers
Un nom de fichier contenant un espace doit être mis entre guillemets pour être passé comme un seul argument.
./args.sh "my file.txt" report.txt$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]Sans guillemets, my et file.txt ont été séparés et $# est passé à 3. Passé ainsi à ls ou cat, ils chercheraient deux fichiers nommés my et file.txt.
./args.sh my file.txt report.txt$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]Les jokers sont remplacés par des noms de fichiers par le shell avant que le programme ne les reçoive. En passant *.txt dans le dossier de travail, les quatre fichiers se terminant par .txt sont arrivés, triés par nom.
./args.sh *.txt$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]Le "*.txt" entre guillemets n'a pas été remplacé par le shell et est devenu un seul argument, caractère pour caractère. Pour les options comme -name de find, où le programme compare lui-même le motif, on le passe ainsi entre guillemets.
./args.sh "*.txt"$0 = ./args.sh
$# = 1
$1 = [*.txt]Des guillemets vides sont aussi passés comme un argument vide. En lançant [./args.sh '' b], $# valait 2 et $1 était vide.
5️⃣ Fin des options d'une commande (--)
Un argument qui commence par un tiret, comme un fichier nommé -n, est lu par la commande comme une option. En lançant [ls -n] dans le dossier dash, qui ne contient que ce fichier, ls a pris -n non pas comme un nom de fichier mais comme l'option d'affichage numérique, et a listé le dossier.
ls -ntotal 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -nLes arguments écrits après -- ne sont pas lus comme des options, même s'ils commencent par un tiret. [ls -- -n] n'a affiché que le nom de fichier -n.
ls -- -n-nDans une même commande, les mêmes caractères sont lus différemment avant et après --. En passant -n deux fois à cat, le premier -n a été lu comme l'option de numéros de ligne et le -n après -- comme un nom de fichier, et le contenu du fichier est sorti avec des numéros de ligne.
cat -n -- -n 1 dash fileOn peut aussi ajouter un chemin et écrire ./-n ; l'argument ne commence alors plus par un tiret et est lu comme le même fichier -n.
Lire -- comme la fin des options est aussi une règle du côté de la commande. Passé à args.sh, qui ne lit pas d'options, -- est allé tel quel dans $1.
./args.sh -- -a$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]Les POSIX Utility Conventions prévoient que le premier -- qui n'est pas un argument d'option soit accepté comme la fin des options. C'est pourquoi, avec les commandes qui suivent ces conventions, on écrit les noms de fichiers commençant par - après --.
6️⃣ Recevoir les arguments de ligne de commande dans un script shell
Un script shell lit les arguments reçus à travers les paramètres positionnels et les paramètres spéciaux. Le main(int argc, char *argv[]) d'un programme C reçoit les mêmes arguments ; mis côte à côte, cela donne ceci.
| Paramètre | Valeur contenue | Fonction main en C |
|---|---|---|
| $0 | Nom du script exécuté | argv[0] |
| $1 ~ $9 | Du premier au neuvième argument | argv[1] ~ argv[9] |
| ${10} | À partir du dixième argument, entre accolades | argv[10] |
| $# | Nombre d'arguments, sans compter $0 | argc - 1 |
| "$@" | Tous les arguments, chacun séparément | De argv[1] jusqu'à la fin |
| "$*" | Tous les arguments réunis en un seul avec des espaces | — |
Un programme Python reçoit les mêmes arguments sous forme de la liste sys.argv. En passant trois arguments avec [python3 -c], le my file.txt entre guillemets est entré dans un seul élément de la liste, et le premier élément contenait -c.
python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l['-c', 'a', 'my file.txt', '-l']"$@" et "$*" donnent des résultats différents lorsqu'ils sont entre guillemets doubles. Pour voir la différence, nous avons créé star.sh, qui affiche les deux formes l'une après l'autre.
#!/bin/bash
echo 'with "$@"'
printf ' [%s]\n' "$@"
echo 'with "$*"'
printf ' [%s]\n' "$*"Nous avons lancé star.sh avec trois arguments : a, "b c" et d.
./star.sh a "b c" dwith "$@"
[a]
[b c]
[d]
with "$*"
[a b c d]"$@" a transmis les trois arguments séparément, tandis que "$*" les a réunis avec des espaces et transmis en un seul.
Pour transmettre tels quels à une autre commande les arguments reçus, on utilise donc "$@".
shift abandonne $1 et avance d'un rang les arguments restants. On l'utilise dans les scripts qui lisent d'abord une option et traitent le reste comme une liste de fichiers.
Nous avons créé shift.sh, qui affiche $1 et $# avant et après shift.
#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift: \$1 = $1, \$# = $#"Nous avons lancé shift.sh avec trois arguments : -v, a.txt et b.txt.
./shift.sh -v a.txt b.txtbefore shift: $1 = -v, $# = 3
after shift: $1 = a.txt, $# = 2À partir du dixième argument, on met le numéro entre accolades, comme ${10}. Nous avons créé ten.sh, qui affiche $10 et ${10} côte à côte.
#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"Nous avons passé 11 arguments à ten.sh, de a à k.
./ten.sh a b c d e f g h i j k$10 = a0
${10} = j$10 a donné a0, soit $1 suivi d'un 0, tandis que ${10} a donné le dixième argument, j.
🔲 Simulateur d'arguments de ligne de commande
Dans le simulateur ci-dessous, vous pouvez passer des guillemets, des jokers et -- à args.sh, et aussi saisir vous-même des commandes pour voir comment ls et getopt lisent les options et comment star.sh et shift.sh reçoivent les arguments.
🔢 FAQ & contenus recommandés
Jokers
[Caractères spéciaux du shell] Jokers Linux (métacaractères)
Un article qui résume, avec des exemples, comment sélectionner des noms de fichiers avec des caractères jokers comme * et ? et avec des classes de caractères.
Commandes multiples
[Linux] 5 façons d'enchaîner des commandes (point-virgule, pipe, esperluette..)
Un article qui résume cinq façons d'exécuter plusieurs commandes sur une seule ligne avec le point-virgule, le pipe, &&, || et &.
Afficher des chaînes
Commande echo : From expansion et protection
Un article qui résume comment afficher des chaînes et des valeurs de variables avec echo, et ses options.
ℹ️ Mention d'affiliation
Le contenu de ce site contient des liens d'affiliation. Lorsqu'un visiteur achète un produit ou un service via l'un de ces liens, le site perçoit une commission du vendeur. Le montant payé par l'acheteur(il baisse lors des promotions ↓), lui, n'augmente pas. Les prix, remises et stocks indiqués correspondent à la date de rédaction et peuvent différer ; vérifiez-les donc auprès du vendeur avant d'acheter. Les produits sont choisis et évalués selon nos propres critères, et les commissions n'influencent ni l'ordre de présentation ni le contenu des évaluations.