리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기
Os argumentos de linha de comando do Linux (command-line argument) são valores passados a um programa escrevendo-os depois do nome do comando, separados por espaços. Ao passar opções, aspas, curingas e -- para um script de teste que mostra exatamente os argumentos que recebe em um servidor AlmaLinux 9, vimos que quem separava os argumentos era o shell e quem lia as opções era cada comando.
A saída abaixo é exatamente a obtida com bash 5.1 na conta root de um servidor AlmaLinux 9.8. Os scripts de teste e os arquivos de exemplo foram criados em uma pasta de trabalho à parte, e o caminho /home/user/www é um valor de exemplo.
1️⃣ O que são argumentos de linha de comando no Linux?
Quando você escreve algo como [comando arg1 arg2] na linha de comando, o shell separa as palavras pelos espaços. A primeira palavra vira o programa a ser executado, e as demais são passadas em ordem a esse programa como argumentos.
Para ver os argumentos recebidos, criamos o args.sh na pasta de trabalho. $0 guarda o nome usado para executá-lo, $# a quantidade de argumentos, e de $1 em diante os argumentos em ordem. Os colchetes foram colocados para mostrar onde cada argumento começa e termina.
#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
echo "\$$i = [$a]"
i=$((i+1))
doneDemos permissão de execução ao script e o executamos com três palavras: a, b e c.
./args.sh a b c$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]As três palavras foram para $1, $2 e $3, e $# foi 3. Se você executar o script escrevendo o nome dele depois de bash, $0 guarda o nome exatamente como foi escrito, args.sh.
bash args.sh a b c$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Só $0 mudou para args.sh; os três argumentos e a quantidade ficaram iguais ao resultado anterior.
2️⃣ Argumentos de linha de comando e opções de comando
Os comandos do Linux costumam ser escritos na ordem [comando -opção argumento]. As opções mudam o modo como o comando funciona, e os argumentos definem os arquivos, caminhos ou valores com que ele trabalha.
ls -l /home/user/wwwPara o shell, -l também é só um argumento. Ao passar as mesmas palavras para o args.sh, -l foi para $1 e o caminho para $2.
./args.sh -l /home/user/www$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]Quem lê -l como opção é o ls. Por isso a mesma letra tem significados diferentes em cada comando: -n no head define quantas linhas mostrar, e -n no ls mostra o dono como número em vez de nome.
Algumas opções pegam como valor próprio a palavra logo depois delas. No comando find, -type usa f e -name usa "*.txt" como valor; um valor ligado a uma opção dessa forma se chama argumento de opção.
find . -type f -name "*.txt"Neste comando, o . do começo é um argumento que não pertence a nenhuma opção e define a pasta onde a busca começa.
3️⃣ Formatos das opções de comandos do Linux
Opções curtas começam com um hífen e têm uma só letra, e várias podem ser escritas juntas. Primeiro listamos a pasta site da pasta de trabalho com [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.htmlEm seguida comparamos com diff a saída de [ls -la], que junta as duas letras.
diff <(ls -l -a site) <(ls -la site) && echo samesameAs duas saídas não diferiram em nenhum caractere. Opções longas começam com dois hífens e são escritas como palavras; --all do ls é a mesma opção que -a, então [ls -l --all site] também deu o mesmo resultado.
Opções longas são aceitas mesmo que você escreva só o começo, desde que ele corresponda a uma única opção. --al correspondia a duas opções, --all e --almost-all, por isso o ls não mostrou a lista e terminou com o código de saída 2.
ls --al sitels: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.Opções que recebem valor podem ser escritas de várias formas. Ao mostrar as duas primeiras linhas de a.txt com head, a opção curta pode ter o valor colado, como em [-n2].
head -n2 a.txtalpha
betaA opção longa liga o valor com um sinal de igual, como em [--lines=2].
head --lines=2 a.txtalpha
betaAs quatro formas, incluindo [-n 2] e [--lines 2] separadas por espaço, mostraram as duas linhas alpha e beta.
ls, head e cat leem suas opções com a função getopt_long da biblioteca C. Ao examinar os três arquivos de programa com strings, todos tinham o nome dessa função.
Para conferir as mesmas regras no shell, usa-se o comando getopt do util-linux. Depois de -o vêm as opções curtas e depois de -l as longas; dois-pontos depois de uma letra indicam que a opção recebe um valor.
getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt -l -a -n '2' --all -- 'a.txt'O -la escrito junto foi separado em -l e -a, e -n 2 foi agrupado como -n com o valor 2. a.txt, que não é opção, foi movido para o fim, depois de --.
4️⃣ Argumentos entre aspas e curingas
Um nome de arquivo com espaço precisa estar entre aspas para ser passado como um único argumento.
./args.sh "my file.txt" report.txt$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]Sem aspas, my e file.txt foram separados e $# passou a 3. Se você passar assim para ls ou cat, eles vão procurar dois arquivos chamados my e file.txt.
./args.sh my file.txt report.txt$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]Os curingas são trocados por nomes de arquivos pelo shell antes de o programa recebê-los. Ao passar *.txt na pasta de trabalho, entraram em ordem alfabética os quatro arquivos que terminam em .txt.
./args.sh *.txt$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]O "*.txt" entre aspas não foi trocado pelo shell e virou um único argumento, letra por letra. Em opções como o -name do find, em que o próprio programa compara o padrão, ele é passado assim, entre aspas.
./args.sh "*.txt"$0 = ./args.sh
$# = 1
$1 = [*.txt]Aspas vazias também são passadas como um argumento vazio. Ao executar [./args.sh '' b], $# foi 2 e $1 ficou vazio.
5️⃣ Fim das opções do comando (--)
Um argumento que começa com hífen, como um arquivo chamado -n, é lido pelo comando como opção. Ao executar [ls -n] na pasta dash, que contém só esse arquivo, o ls tomou -n não como nome de arquivo, mas como a opção de saída numérica, e listou a pasta.
ls -ntotal 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -nArgumentos escritos depois de -- não são lidos como opções, mesmo que comecem com hífen. [ls -- -n] mostrou só o nome de arquivo -n.
ls -- -n-nDentro de um mesmo comando, os mesmos caracteres são lidos de forma diferente antes e depois de --. Ao passar -n duas vezes para o cat, o primeiro -n foi lido como a opção de números de linha e o -n depois de -- como nome de arquivo, e o conteúdo do arquivo saiu com números de linha.
cat -n -- -n 1 dash fileTambém dá para acrescentar o caminho e escrever ./-n; nesse caso o argumento não começa com hífen e é lido como o mesmo arquivo -n.
Ler -- como o fim das opções também é uma regra do lado do comando. Ao passá-lo para o args.sh, que não lê opções, -- também foi para $1 sem mudanças.
./args.sh -- -a$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]As Convenções de Utilitários do POSIX determinam que o primeiro -- que não seja argumento de opção seja aceito como o fim das opções. Por isso, nos comandos que seguem essas convenções, nomes de arquivos que começam com - são escritos depois de --.
6️⃣ Receber argumentos de linha de comando em um script shell
Um script shell lê os argumentos recebidos por meio de parâmetros posicionais e parâmetros especiais. O main(int argc, char *argv[]) de um programa em C recebe os mesmos argumentos; colocando os dois lado a lado, fica assim.
| Parâmetro | Valor que contém | Função main em C |
|---|---|---|
| $0 | Nome do script executado | argv[0] |
| $1 ~ $9 | Do primeiro ao nono argumento | argv[1] ~ argv[9] |
| ${10} | A partir do décimo argumento, entre chaves | argv[10] |
| $# | Quantidade de argumentos, sem contar $0 | argc - 1 |
| "$@" | Todos os argumentos, cada um separado | De argv[1] até o fim |
| "$*" | Todos os argumentos unidos em um só com espaços | — |
Um programa em Python recebe os mesmos argumentos como a lista sys.argv. Ao passar três argumentos com [python3 -c], o my file.txt entre aspas entrou em um único item da lista, e o primeiro item recebeu -c.
python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l['-c', 'a', 'my file.txt', '-l']"$@" e "$*" dão resultados diferentes quando ficam entre aspas duplas. Para ver a diferença, criamos o star.sh, que mostra as duas formas uma depois da outra.
#!/bin/bash
echo 'with "$@"'
printf ' [%s]\n' "$@"
echo 'with "$*"'
printf ' [%s]\n' "$*"Executamos o star.sh com três argumentos: a, "b c" e d.
./star.sh a "b c" dwith "$@"
[a]
[b c]
[d]
with "$*"
[a b c d]"$@" passou os três argumentos separados, enquanto "$*" os uniu com espaços e passou como um só.
Por isso, para repassar os argumentos recebidos a outro comando sem mudanças, use "$@".
shift descarta $1 e adianta os argumentos restantes uma posição. É usado em scripts que leem primeiro uma opção e tratam o resto como uma lista de arquivos.
Criamos o shift.sh, que mostra $1 e $# antes e depois do shift.
#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift: \$1 = $1, \$# = $#"Executamos o shift.sh com três argumentos: -v, a.txt e b.txt.
./shift.sh -v a.txt b.txtbefore shift: $1 = -v, $# = 3
after shift: $1 = a.txt, $# = 2A partir do décimo argumento, o número vai entre chaves, como em ${10}. Criamos o ten.sh, que mostra $10 e ${10} lado a lado.
#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"Passamos 11 argumentos, de a até k, para o ten.sh.
./ten.sh a b c d e f g h i j k$10 = a0
${10} = j$10 saiu como a0, ou seja, $1 seguido de um 0, enquanto ${10} saiu como o décimo argumento, j.
🔲 Simulador de argumentos de linha de comando
No simulador abaixo, você pode passar aspas, curingas e -- para o args.sh e também digitar comandos para ver como ls e getopt leem as opções e como star.sh e shift.sh recebem os argumentos.
🔢 FAQ & conteúdo recomendado
Curingas
[Caracteres especiais do shell] Curingas do Linux (metacaracteres)
Artigo que resume, com exemplos, como selecionar nomes de arquivos com caracteres curinga como * e ? e com classes de caracteres.
Vários comandos
[Linux] 5 formas de encadear comandos (ponto e vírgula, pipe, e comercial..)
Artigo que resume cinco formas de executar vários comandos em uma só linha com ponto e vírgula, pipe, &&, || e &.
Mostrar textos
Comando echo: From expansão e aspas
Artigo que resume como mostrar textos e valores de variáveis com echo, e suas opções.
ℹ️ Aviso de afiliados
O conteúdo deste site contém links de afiliados. Quando um visitante compra um produto ou serviço por meio de um desses links, o site recebe uma comissão do vendedor. O valor que o comprador paga (em promoções, ele diminui ↓) não aumenta por causa disso. Preços, descontos e informações de estoque valem para o momento em que o texto foi escrito e podem ter mudado, por isso confirme com o vendedor antes de comprar. Os produtos são escolhidos e avaliados por critérios próprios, e o recebimento de comissão não influencia a ordem de apresentação nem o conteúdo das avaliações.