Tutorial de Shell Script para Iniciantes - Variáveis, If e Loops no Bash
O que você vai conseguir fazer
- Criar e executar seus próprios scripts com shebang e permissão de execução
- Automatizar trabalho combinando variáveis, condicionais e loops
- Isolar e corrigir as causas dos erros de sintaxe mais comuns
Pré-requisitos (leia estes primeiro)
Um shell script é um arquivo que reúne os comandos que você digitaria no terminal, para que possam ser executados de uma vez. "Shell script", "script bash" e "programa de shell" significam a mesma coisa.
Coloque em um arquivo o trabalho que antes era digitado à mão e, na próxima vez, uma única execução resolve. Esta edição de fundamentos cobre a sintaxe do Bash desde variáveis e condicionais até loops.
O Que Você Vai Aprender
- Você vai conseguir criar e executar seus próprios scripts, entendendo a linha shebang e a permissão de execução.
- Você vai conseguir automatizar trabalho repetitivo combinando variáveis, condicionais e loops.
- Você vai conseguir isolar e corrigir as causas dos erros de sintaxe mais comuns.
Para quem é: quem já digitou comandos no terminal e quer automatizar o trabalho que se repete.
Pré-requisitos: este artigo lê variáveis como $HOME. Se isso for novo para você, leia primeiro Fundamentos de Variáveis de Ambiente.
Termos definidos antes de começar
Cada termo abaixo é definido uma única vez, aqui.
- Um shell é o programa que recebe os comandos digitados e os executa. No Linux, o Bash é o padrão.
- Um shebang é a linha
#!/bin/bashno topo do script. Também é chamado de hashbang. Ela declara qual shell deve executar o arquivo. - A permissão de execução é a permissão que autoriza um arquivo a ser iniciado como programa. Um script sem ela para com
Permission denied. - Uma variável é uma caixa que guarda um valor sob um nome.
name="valor"coloca o valor dentro;$nameo retira. - Aspas são
"e'. Se um valor contém espaços, o shell o lê como palavras separadas caso não esteja entre aspas. - O status de saída é o número de 0 a 255 que um comando devolve ao terminar. 0 significa sucesso e qualquer outro valor significa falha. Também é chamado de código de saída ou código de retorno.
- A substituição de comando é a forma
$(date), que embute a saída de um comando no lugar. - A expansão aritmética é a forma
$((1 + 2)), que embute o resultado de um cálculo. Sem ela, o shell trata números como texto, então cálculos exigem essa forma. Ela lida apenas com inteiros, e a parte fracionária é descartada.
Seu Primeiro Shell Script
Conclusão: #!/bin/bash, chmod +x, ./script.sh -- três passos que iniciam todo script Bash.
Estrutura Básica
#!/bin/bash # Isso e um comentario echo "Ola, Shell Script!" echo "Data/hora atual: $(date)" echo "Nome de usuario: $USER"
Criando e Executando Scripts
Passo 1: Criar Arquivo
$ nano hello.sh
Digite o código acima e salve.
Passo 2: Adicionar Permissão de Execução
$ chmod +x hello.sh
Passo 3: Executar Script
$ ./hello.sh
Ola, Shell Script! Data/hora atual: Sat Jan 11 14:30:00 JST 2025 Nome de usuario: user
O formato que o date imprime depende do locale. Em um locale japonês (ja_JP.UTF-8), por exemplo, a saída sai como 2025年 1月11日 土曜日 14時30分00秒 JST.
O ./ em ./hello.sh significa "no diretório em que estou". Sem ele, o shell procura apenas no PATH, o que termina em command not found.
O script executa sem condições o que estiver escrito nele
Um script não mostra tela de confirmação. Se houver um rm dentro, a exclusão simplesmente acontece. O que acontece quando dá errado se resume a dois pontos.
- Executar um script sem ler antes significa que qualquer exclusão ou sobrescrita dentro dele não pode ser desfeita.
- Executar como
sudo ./script.shroda todas as operações internas com privilégio de root, deixando arquivos de sistema ao alcance.
Como testar com segurança envolve três hábitos.
- Pratique apenas dentro de um diretório dedicado:
mkdir ~/script-practice && cd ~/script-practice. - Leia o script de outra pessoa com
cat script.shantes de executar. - Execute primeiro sem
sudo. Se aparecer erro de permissão, então descubra por que ele é necessário.
Sobre o Shebang
#!/bin/bash é chamado de shebang e especifica o interpretador, ou seja, o programa responsável por executar o arquivo.
#!/bin/bash-- Usar Bash#!/bin/sh-- Usar shell POSIX#!/usr/bin/env bash-- Auto-detectar do ambiente
Se o shebang for esquecido, o comportamento depende de qual shell acabar executando o arquivo. Com #!/bin/sh, em especial, a sintaxe exclusiva do Bash (como [[ ]] e arrays) não está disponível. Na dúvida, escreva #!/bin/bash.
Variáveis e Entrada
Conclusão: Sem espaços ao redor do =; entre aspas todos os usos; use $() para substituição; read -p para entrada.
Fundamentos de Variáveis
#!/bin/bash
# Definir variaveis (sem espacos ao redor do =)
name="Usuario Linux"
age=25
today=$(date +%Y-%m-%d)
# Usar variaveis
echo "Nome: $name"
echo "Idade: ${age} anos"
echo "Data de hoje: $today"Exemplo de Cálculo
#!/bin/bash num1=10 num2=3 sum=$((num1 + num2)) diff=$((num1 - num2)) product=$((num1 * num2)) quotient=$((num1 / num2)) echo "Adicao: $num1 + $num2 = $sum" echo "Subtracao: $num1 - $num2 = $diff" echo "Multiplicacao: $num1 x $num2 = $product" echo "Divisao: $num1 / $num2 = $quotient"
Adicao: 10 + 3 = 13 Subtracao: 10 - 3 = 7 Multiplicacao: 10 x 3 = 30 Divisao: 10 / 3 = 3
O resultado 3 na divisão não é um erro. A expansão aritmética do shell é aritmética de inteiros, e a parte fracionária é descartada ($((10 / 3)) dá 3). Quando precisar de decimais, use bc ou awk.
echo "scale=2; 10/3" | bc # 3.33
awk 'BEGIN {print 10/3}' # 3.33333Variáveis Especiais
| Variável | Descrição | Exemplo |
|---|---|---|
$0 |
Nome do script | ./script.sh |
$1, $2, ... |
Argumentos da linha de comando | 1o arg, 2o arg |
$# |
Número de argumentos | 3 para 3 argumentos |
$@ |
Todos os argumentos | "arg1" "arg2" "arg3" |
$? |
Status de saída do último comando | 0 para sucesso, não-0 para falha |
$$ |
ID do processo atual | 12345 |
$USER |
Nome de usuário atual | user |
$HOME |
Diretório home | /home/user |
$PWD |
Diretório atual | /home/user/scripts |
Entrada do Usuário
Entrada Básica
#!/bin/bash
echo "Por favor, digite seu nome:"
read name
echo "Ola, ${name}!"Entrada com Prompt
#!/bin/bash read -p "Digite sua idade: " age read -s -p "Digite a senha: " password echo echo "Idade: $age" echo "Senha digitada silenciosamente"
Múltiplos Valores de Uma Vez
#!/bin/bash echo "Digite nome e idade (separados por espaco):" read name age echo "Nome: $name, Idade: $age"
Condicionais
Conclusão: Espaços dentro de [ ] obrigatórios; variáveis de string entre aspas; use -eq/-gt/-lt para números.
Instrução if
Instrução if Básica
#!/bin/bash
read -p "Digite um numero: " num
if [ "$num" -gt 0 ]; then
echo "$num e positivo"
elif [ "$num" -lt 0 ]; then
echo "$num e negativo"
else
echo "$num e zero"
fiVerificação de Existência de Arquivo
#!/bin/bash
filename="test.txt"
if [ -f "$filename" ]; then
echo "$filename existe"
echo "Tamanho do arquivo: $(wc -c < "$filename") bytes"
else
echo "$filename nao existe"
echo "Criando arquivo..."
touch "$filename"
fiOperadores Condicionais
Comparação Numérica
| Operador | Significado | Exemplo |
|---|---|---|
-eq |
Igual | [ $a -eq $b ] |
-ne |
Diferente | [ $a -ne $b ] |
-gt |
Maior que | [ $a -gt $b ] |
-ge |
Maior ou igual | [ $a -ge $b ] |
-lt |
Menor que | [ $a -lt $b ] |
-le |
Menor ou igual | [ $a -le $b ] |
Comparação de Strings
| Operador | Significado | Exemplo |
|---|---|---|
= |
Igual | [ "$a" = "$b" ] |
!= |
Diferente | [ "$a" != "$b" ] |
-z |
String vazia | [ -z "$str" ] |
-n |
Não vazia | [ -n "$str" ] |
Testes de Arquivo
| Operador | Significado | Exemplo |
|---|---|---|
-f |
Arquivo regular | [ -f file.txt ] |
-d |
Diretório | [ -d /home ] |
-e |
Existe | [ -e path ] |
-r |
Legível | [ -r file ] |
-w |
Gravável | [ -w file ] |
-x |
Executável | [ -x script ] |
Instrução case
#!/bin/bash
echo "Selecione uma opcao:"
echo "1) Listar arquivos"
echo "2) Mostrar hora atual"
echo "3) Mostrar info do sistema"
echo "4) Sair"
read -p "Escolha (1-4): " choice
case $choice in
1)
echo "=== Lista de Arquivos ==="
ls -la
;;
2)
echo "=== Hora Atual ==="
date
;;
3)
echo "=== Info do Sistema ==="
uname -a
;;
4)
echo "Saindo."
exit 0
;;
*)
echo "Escolha invalida."
;;
esacLoops
Conclusão: {1..N} para intervalos, while IFS= read para linhas de arquivo, until para condições inversas.
Loop for
Loop for Básico
#!/bin/bash
# Intervalo numerico
for i in {1..5}
do
echo "Contagem: $i"
done
echo "---"
# Processamento de arquivos
for file in *.txt
do
echo "Processando: $file"
wc -l "$file"
doneLoop com Arrays
#!/bin/bash
fruits=("apple" "banana" "orange" "grape")
echo "Lista de frutas:"
for fruit in "${fruits[@]}"
do
echo "- $fruit"
doneLoop for Estilo C
#!/bin/bash
echo "Tabela de multiplicacao (parcial):"
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
result=$((i * j))
printf "%2d " $result
done
echo
doneLoop while
Loop while Básico
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "Iteracao do loop $count"
count=$((count + 1))
doneLendo Arquivos
#!/bin/bash
filename="data.txt"
if [ -f "$filename" ]; then
while IFS= read -r line
do
echo "Lido: $line"
done < "$filename"
else
echo "Arquivo $filename nao encontrado"
fiLoop until
#!/bin/bash
count=1
until [ $count -gt 5 ]
do
echo "Contagem: $count"
count=$((count + 1))
doneControle de Loop
- break -- Sair do loop
- continue -- Pular para a próxima iteração
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 3 ]; then
echo "Pulando 3"
continue
fi
if [ $i -eq 8 ]; then
echo "Parando em 8"
break
fi
echo "Numero: $i"
doneErros Comuns de Iniciantes e Armadilhas
Conclusão: Seis armadilhas em scripts Bash: espacamento, chaves, colchetes, aspas, crases, matemática.
Erro 1: Espaços na Atribuição de Variável
NG (causa erro)
name = "Taro" # Espaco antes/depois do = age= 25 # Espaco depois do = city ="Tokyo" # Espaco antes do =
Resulta em erro "command not found".
OK (uso correto)
name="Taro" # Sem espacos ao redor do = age=25 city="Tokyo"
A atribuição de variável não pode ter espaços ao redor do =.
Erro 2: Chaves Ausentes na Referência de Variável
NG (resultados inesperados)
filename="test" echo "$filenameback.txt" # imprime apenas ".txt" ($filenameback e indefinida) echo "$filename_backup" # nao imprime nada ($filename_backup e indefinida)
O shell lê $filenameback como um único nome de variável. Ele nunca divide isso em $filename mais back.
OK (uso correto)
filename="test"
echo "${filename}back.txt" # testback.txt
echo "${filename}_backup" # test_backupUse {} para definir claramente o escopo do nome da variável.
Erro 3: Espaços Ausentes nas Condições do if
NG (erro de sintaxe)
if [$num -gt 5]; then # Sem espaco depois do [ if [ $num -gt 5]; then # Sem espaco antes do ]
OK (uso correto)
if [ $num -gt 5 ]; then # Espacos dentro de [ ] obrigatorios if [[ $num -gt 5 ]]; then # Mesmo para [[ ]] if (( num > 5 )); then # Expressao aritmetica
Erro 4: Aspas Ausentes na Comparação de Strings
NG (exemplos perigosos)
if [ $name = John Doe ]; then # Problemas com espacos if [ $empty_var = "" ]; then # Erro quando vazio
OK (uso seguro)
if [ "$name" = "John Doe" ]; then # Aspas em ambos os lados if [ "$empty_var" = "" ]; then # Sem erro quando vazio if [ -z "$var" ]; then # Opcao dedicada para verificar vazio
Erro 5: Sintaxe Antiga de Substituição de Comando
NG (não recomendado)
date=`date` # Crases result=`cat `which ls`` # Aninhamento causa erro
OK (sintaxe moderna)
date=$(date) # Use $() result=$(cat $(which ls)) # Facil de aninhar
Erro 6: Erros de Operação Aritmética
NG (não calculado)
result = $num1 + $num2 # Interpretado como comando "result" (command not found) sum="$a + $b" # Nao calculado
OK (métodos corretos de cálculo)
result=$((num1 + num2)) # Expansao aritmetica let "result = num1 + num2" # Usar comando let
Regras Básicas para Prevenir Erros
Fundamentos de Escrita
- Atribuição de variável: sem espaços ao redor do
= - Uso de variável: sempre entre aspas
"$var" - Variáveis complexas: use chaves
"${var}"
Fundamentos de Condicionais
- Usando
[ ]: sempre inclua espaços internos - Comparação de strings: aspas em ambos os lados
- Comparação numérica: use
-eq,-gt,-lt, etc.
Depuração e Solução de Problemas
Quando um script não funciona como esperado, não chute: use set -x para exibir o rastro de execução. Ver como cada variável foi expandida, linha por linha, torna a causa fácil de identificar.
set -x: exibir o rastro de execução
#!/bin/bash
set -x # exibir cada comando a partir daqui
filename="data.txt"
echo "DEBUG: filename = [$filename]"
if [ ! -f "$filename" ]; then
echo "ERRO: Arquivo $filename nao encontrado" >&2
exit 1
fi+ filename=data.txt + echo 'DEBUG: filename = [data.txt]' DEBUG: filename = [data.txt] + '[' '!' -f data.txt ']' + echo 'ERRO: Arquivo data.txt nao encontrado' ERRO: Arquivo data.txt nao encontrado + exit 1
As linhas que começam com + são os comandos que o shell realmente executou. Como você as vê depois da expansão das variáveis, causas como "a variável estava vazia" ou "as aspas não valeram" ficam identificáveis na hora. O valor é impresso entre [ ] para distinguir uma string vazia de um único espaço.
set -e / set -u: parar problemas cedo
#!/bin/bash set -e # parar assim que um comando falhar set -u # parar assim que uma variavel indefinida for referenciada
Esses dois existem para impedir que o processamento siga adiante sem que o problema seja notado. O set -u é especialmente eficaz para pegar erros de digitação em nomes de variável.
Em um script com set -u habilitado, referenciar uma variável indefinida interrompe a execução naquela linha com um erro unbound variable. Esse é o comportamento pretendido, não uma falha do set -x.
script.sh: line 5: var: unbound variable
Onde você não quiser que pare, forneça um valor padrão como ${var:-}, que trata a variável indefinida como string vazia.
Mensagens de Erro Comuns e Soluções
Sintoma: command not found
Causa: espaços ao redor do = em uma atribuição de variável, ou execução do script sem ./.
Verificação:
bash -n script.sh # apenas checagem de sintaxe (nao executa)
Correção: remova os espaços ao redor do =. Chame o script como ./script.sh.
Sintoma: Permission denied
Causa: o script não tem permissão de execução.
Verificação:
ls -l script.sh
A ausência de x em algo como -rw-r--r-- indica que não há permissão de execução.
Correção:
chmod +x script.sh
Sintoma: syntax error near unexpected token
Causa: espaços ausentes dentro de [ ], aspas não fechadas ou then / fi / done ausentes.
Verificação:
bash -n script.sh
Correção: revise as linhas em torno do número informado. O if precisa de then e fi correspondentes; for e while precisam de do e done.
Sintoma: uma variável sai vazia
Causa: caracteres seguem o nome da variável diretamente, e o shell lê tudo como outra variável.
Verificação:
echo "DEBUG: var = [$var]"
Os colchetes permitem distinguir uma string vazia de uma que contém espaços.
Correção: escreva ${var} para delimitar onde o nome da variável termina.
Checklist de Conclusão
- [ ] Escreveu um shebang (
#!/bin/bash) na primeira linha - [ ] Adicionou permissão de execução com
chmod +x - [ ] Não deixou espaços ao redor do
=nas atribuições - [ ] Usou aspas nas referências de variável, na forma
"$var" - [ ] Executou dentro de um diretório de prática, sem
sudo, para confirmar o comportamento - [ ] Usou
bash -neset -xpara isolar a causa quando não funcionou