Ubuntu Variáveis e Argumentos

Uma variável é um nome que guarda um valor: um texto, um número, o resultado de um comando. Com variáveis, um script deixa de fazer sempre a mesma coisa e passa a se adaptar: ao usuário, à data de hoje, ao arquivo que você passou na linha de comando.

Você vai aprender
  • Criar e ler variáveis, e a regra de ouro: sem espaços em volta do =.
  • A diferença entre aspas simples, duplas e nenhuma aspa.
  • Guardar a saída de um comando com $( ) e fazer contas com $(( )).
  • Ler o que o usuário digita (read) e os argumentos do script ($1, $#, $@).
  • Valores padrão e recortes de texto: tirar extensão, pegar o nome do arquivo.

Criar e ler uma variável

nome
O nome da variável. Use letras, números e _; não pode começar com número.
=
Atribui o valor. Sem espaços antes nem depois.
"Ana Maria"
O valor. As aspas são necessárias porque ele tem espaço.
$ nome="Ana Maria"
$ echo $nome
Ana Maria
$ echo "Olá, $nome!"
Olá, Ana Maria!

Para ler a variável, coloque $ antes do nome. O bash troca $nome pelo valor antes de rodar o comando. Criar a variável não mostra nada: silêncio, como sempre, é sucesso.

Chaves: onde o nome termina

Quando o nome da variável fica colado em outro texto, o bash não sabe onde ele termina. As chaves resolvem:

$ fruta=banana
$ echo "Comprei 3 $frutas"
Comprei 3                                  « procurou a variável "frutas", que não existe
$ echo "Comprei 3 ${fruta}s"
Comprei 3 bananas
Convenção de nomes

Variáveis do sistema são MAIÚSCULAS (HOME, PATH). Nos seus scripts, prefira minúsculas (pasta_destino) para não sobrescrever uma variável do sistema sem querer.

Missão: crie uma variável cidade com o nome da sua cidade e mostre a frase Eu moro em … usando echo e $cidade. Depois tente cidade = Recife, com espaços, e veja o erro.


Aspas: simples, duplas ou nenhuma

As aspas mudam o que o bash faz com o texto. Esta é a parte mais importante da aula:

$ nome="Ana"
$ echo "Olá, $nome"                        « duplas: troca as variáveis
Olá, Ana
$ echo 'Olá, $nome'                        « simples: tudo literal
Olá, $nome
$ echo Olá,     $nome                      « sem aspas: espaços extras somem
Olá, Ana
Forma$variável é trocada?Espaços preservados?Use para
"texto $var"SimSimQuase tudo. É o padrão seguro.
'texto $var'NãoSimTexto que deve sair exatamente como está.
texto $varSimNão: o valor é quebrado em palavrasEvite com variáveis.

Por que sempre usar aspas em volta de variáveis

Sem aspas, um valor com espaço vira vários argumentos. Veja o que acontece ao criar um arquivo:

$ arquivo="Meu Relatório.pdf"
$ touch $arquivo
$ ls
Meu  Relatório.pdf                         « dois arquivos!
$ arquivo="Meu Relatório.pdf"
$ touch "$arquivo"
$ ls
'Meu Relatório.pdf'                        « um arquivo, como esperado

Regra prática: escreva "$variável", com aspas duplas, sempre que usá-la como argumento.


Guardar a saída de um comando: $( )

A substituição de comando roda o comando de dentro e coloca a saída dele no lugar. Combinada com uma variável, guarda o resultado para usar depois.

hoje=
A variável que vai receber o resultado.
$(
Abre a substituição: "rode o que vem a seguir".
date +%F
O comando: a data no formato 2026-10-15.
)
Fecha a substituição.
$ hoje=$(date +%F)
$ echo "Backup de $hoje"
Backup de 2026-10-15
$ qtd=$(ls ~/Downloads | wc -l)
$ echo "Há $qtd arquivos em Downloads"
Há 5 arquivos em Downloads

Em scripts antigos você vai ver a forma com crases: hoje=`date +%F`. Ela funciona, mas a forma $( ) é mais legível e pode ser aninhada.

Missão: guarde a data de hoje numa variável chamada pasta, usando $(date +%F), e crie uma pasta com esse nome usando mkdir "$pasta". Confira com ls.


Contas: $(( ))

Para o bash, tudo é texto. Para fazer contas com números inteiros, use dois parênteses:

$ a=7
$ b=2
$ echo $((a + b))
9
$ echo $((a / b))                          « divisão inteira: sem casas decimais
3
$ echo $((a % b))                          « resto da divisão
1
$ echo $((2 ** 10))                        « potência
1024
$ contador=5
$ ((contador++))
$ echo $contador
6

Dentro de $(( )) não precisa do $ antes das variáveis. Para números com vírgula, use o bc: echo "7/2" | bc -l.

Formas de fazer contas

$(( )) é a forma moderna. Você também pode ver let "n = n + 1" e expr 7 + 2, que são mais antigas e fazem o mesmo.


Ler o que o usuário digita: read

O read pausa o script, espera o usuário digitar e guarda o texto numa variável.

read
O comando que lê do teclado.
-r
Lê as barras invertidas \ literalmente. Use sempre.
-p "Seu nome: "
Prompt: mostra uma pergunta antes.
nome
A variável que vai receber a resposta.
#!/usr/bin/env bash
read -rp "Seu nome: " nome
read -rsp "Uma senha: " senha
echo                               # pula a linha depois da senha
echo "Olá, $nome! Sua senha tem ${#senha} caracteres."
$ ./cadastro.sh
Seu nome: Ana
Uma senha:                         « -s: o que você digita não aparece
Olá, Ana! Sua senha tem 8 caracteres.

Argumentos: o que vem depois do nome do script

Em vez de perguntar com read, o script pode receber informações na própria linha de comando, como qualquer programa. Cada palavra depois do nome é um argumento, guardado em variáveis numeradas:

#!/usr/bin/env bash
echo "Script: $0"
echo "Primeiro: $1"
echo "Segundo: $2"
echo "Quantidade: $#"
echo "Todos: $@"
./args.sh
O script: fica em $0.
foto.jpg
O 1º argumento: $1.
"Meu Relatório.pdf"
O 2º argumento: $2. Com aspas, é um argumento só.
$ ./args.sh foto.jpg "Meu Relatório.pdf"
Script: ./args.sh
Primeiro: foto.jpg
Segundo: Meu Relatório.pdf
Quantidade: 2
Todos: foto.jpg Meu Relatório.pdf
VariávelContém
$0O nome do script, como foi chamado
$1 … $9Os argumentos 1 a 9 (do 10 em diante: ${10})
$#Quantos argumentos foram passados
"$@"Todos os argumentos, cada um separado, mesmo com espaços. Use este.
$*Todos juntos num texto só. Raramente é o que você quer.
$?Código de saída do último comando
$$O PID (número do processo) do próprio script
$RANDOMUm número aleatório de 0 a 32767

shift: andar pela lista de argumentos

O shift descarta o $1 e "puxa" os outros: o $2 vira $1, e assim por diante. É útil quando o primeiro argumento é especial e o resto é uma lista:

#!/usr/bin/env bash
destino="$1"
shift                                  # agora "$@" tem só os arquivos
cp -v "$@" "$destino"
$ ./copiar-para.sh /media/ana/PENDRIVE notas.txt foto.jpg
'notas.txt' -> '/media/ana/PENDRIVE/notas.txt'
'foto.jpg' -> '/media/ana/PENDRIVE/foto.jpg'

Valores padrão e argumentos obrigatórios

E se o usuário não passar um argumento? O bash tem atalhos para isso:

${1
O primeiro argumento…
:-
…mas, se ele estiver vazio ou não existir…
.}
…use . (a pasta atual) no lugar.
#!/usr/bin/env bash
pasta="${1:-.}"
echo "A pasta $pasta tem $(ls "$pasta" | wc -l) itens."
$ ./scripts/conta.sh ~/Downloads
A pasta /home/ana/Downloads tem 5 itens.
$ ./scripts/conta.sh
A pasta . tem 9 itens.

Quando o argumento é obrigatório, use :?. O script para com a mensagem que você escolher:

#!/usr/bin/env bash
pasta="${1:?informe a pasta}"
find "$pasta" -type f -mtime +30 -print
$ ./apaga-antigos.sh
./apaga-antigos.sh: linha 2: 1: informe a pasta
FormaSignifica
${var:-padrão}Usa "padrão" se var estiver vazia (não altera var)
${var:=padrão}Igual, mas também guarda "padrão" em var
${var:?mensagem}Para o script com a mensagem se var estiver vazia

Recortar e transformar texto

O bash consegue mexer no valor da variável sem chamar outros programas. As formas mais úteis no dia a dia:

$ arq="ferias.tar.gz"
$ echo ${#arq}                              « tamanho do texto
13
$ echo ${arq%.*}                            « tira a última extensão
ferias.tar
$ echo ${arq%%.*}                           « tira todas as extensões
ferias
$ echo ${arq#*.}                            « tira até o primeiro ponto
tar.gz
$ echo ${arq/ferias/praia}                  « troca um trecho
praia.tar.gz
$ echo ${arq^^}                             « tudo maiúsculo
FERIAS.TAR.GZ
$ caminho=/home/ana/Documentos/notas.txt
$ echo ${caminho##*/}                       « só o nome do arquivo
notas.txt
$ echo ${caminho%/*}                        « só a pasta
/home/ana/Documentos
FormaLembrete
${var#padrão} / ${var##padrão}Tira do começo (# = o menor trecho, ## = o maior)
${var%padrão} / ${var%%padrão}Tira do fim (% = o menor, %% = o maior)
${var/de/para}Troca a primeira ocorrência; ${var//de/para} troca todas
${var^^} / ${var,,}Tudo maiúsculo / tudo minúsculo

Essas formas também têm equivalentes com comandos externos: basename caminho (= ${caminho##*/}) e dirname caminho (= ${caminho%/*}).


Listas: arrays

Um array guarda vários valores numa variável só. As posições começam em 0:

$ frutas=(maçã banana uva)
$ echo ${frutas[1]}                         « posição 1 = o segundo item
banana
$ echo ${#frutas[@]}                        « quantos itens
3
$ frutas+=(kiwi)                            « acrescenta no fim
$ echo "${frutas[@]}"
maçã banana uva kiwi

Você vai percorrer arrays com for em Laços.


Um script completo

Juntando tudo: um script que faz backup de uma pasta, com nome padrão e data no arquivo:

#!/usr/bin/env bash
set -euo pipefail

origem="${1:?uso: backup-pasta PASTA [DESTINO]}"
destino="${2:-$HOME/backups}"
nome="$(basename "$origem")-$(date +%F).tar.gz"

mkdir -p "$destino"
tar -czf "$destino/$nome" -C "$(dirname "$origem")" "$(basename "$origem")"

tamanho=$(du -h "$destino/$nome" | cut -f1)
echo "Backup criado: $destino/$nome ($tamanho)"
$ backup-pasta ~/Documentos
Backup criado: /home/ana/backups/Documentos-2026-10-15.tar.gz (8,0K)
$ backup-pasta
/home/ana/.local/bin/backup-pasta: linha 4: 1: uso: backup-pasta PASTA [DESTINO]

Quando não funciona

"comando não encontrado" ao criar a variável
$ nome = Ana
nome: comando não encontrado

O que aconteceu: com espaços, o bash acha que nome é um comando e = e Ana são argumentos dele.

Como resolver: nome=Ana, tudo junto.

A variável aparece vazia
$ echo "Arquivo: $arqivo"
Arquivo:

O que aconteceu: o nome foi digitado errado (arqivo), ou a variável foi criada em outro terminal, ou dentro de um script que já terminou. Para o bash, uma variável que não existe vale "vazio", sem erro.

Como resolver: confira o nome. Em scripts, set -u transforma isso em erro: linha 3: arqivo: variável não associada.

Arquivo com espaço virou dois

O que aconteceu: faltaram aspas: cp $arquivo /backup com arquivo="Meu Relatório.pdf" vira cp Meu Relatório.pdf /backup, e o cp procura dois arquivos.

Como resolver: cp "$arquivo" /backup.

"$variavel" aparece literalmente na tela
$ echo 'Bem-vinda, $USER'
Bem-vinda, $USER

O que aconteceu: aspas simples desligam a troca de variáveis.

Como resolver: use aspas duplas: echo "Bem-vinda, $USER".

"a variável permite somente leitura" e "divisão por 0"
$ readonly PI=3
$ PI=4
bash: PI: a variável permite somente leitura
$ echo $((10 / 0))
bash: 10 / 0: divisão por 0 (token de erro é "0")

O que aconteceu: readonly trava a variável, e divisão por zero é proibida. Os dois param o comando com erro.


Exercícios

1. Criar e usar

Complete para criar a variável cor com o valor azul:

2. Saída de comando

Complete para guardar o nome da máquina na variável maquina:

maquina=

3. Quantidade de argumentos

Complete para o script mostrar quantos argumentos recebeu:

echo "Recebi argumentos"

4. Valor padrão

Complete para usar /tmp quando o primeiro argumento não for informado:

pasta="${1}"

5. Com nome="Ana", o que mostra echo 'Oi, $nome'?


Resumo

  • nome=valor cria (sem espaços); $nome ou ${nome} lê.
  • Aspas duplas trocam variáveis e preservam espaços; simples deixam tudo literal. Use "$var" sempre.
  • $(comando) guarda a saída de um comando; $(( )) faz contas inteiras.
  • read -rp pergunta ao usuário; $1, $# e "$@" trazem os argumentos.
  • ${1:-padrão} dá um valor padrão; ${1:?msg} torna obrigatório; ${arq%.*} tira a extensão.