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.
- 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
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" | Sim | Sim | Quase tudo. É o padrão seguro. |
'texto $var' | Não | Sim | Texto que deve sair exatamente como está. |
texto $var | Sim | Não: o valor é quebrado em palavras | Evite 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.
$(( )) é 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ável | Contém |
|---|---|
$0 | O nome do script, como foi chamado |
$1 … $9 | Os 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 |
$RANDOM | Um 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
| Forma | Significa |
|---|---|
${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
| Forma | Lembrete |
|---|---|
${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
$ 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.
$ 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.
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.
$ 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".
$ 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:
3. Quantidade de argumentos
Complete para o script mostrar quantos argumentos recebeu:
4. Valor padrão
Complete para usar /tmp quando o primeiro argumento não for informado:
5. Com nome="Ana", o que mostra echo 'Oi, $nome'?
Resumo
nome=valorcria (sem espaços);$nomeou${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 -rppergunta 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.