Tutorial de Linux / Crie seu primeiro script Bash com variáveis, condições e repetições
Um script de shell reúne comandos e o fluxo de execução em um programa reutilizável. Para criar seu primeiro script Bash, proteja as expansões de variáveis com aspas, valide os argumentos e confira o estado de saída ao testar cada comportamento.
Nesta aula, você cria e executa um programa salvo em arquivo. Consulte o fluxo de execução do shell para revisar variáveis e operadores; a aula sobre erros no Bash e operações seguras com arquivos, em inglês aprofunda as limitações relacionadas a falhas, caminhos e execução simultânea.
Escolha o Bash e prepare uma pasta de trabalho
O exercício foi escrito para Bash no Ubuntu e no Rocky Linux. Recursos como [[ ... ]] e arrays não funcionam necessariamente em outros interpretadores sh; por isso, não execute um script Bash com sh script.sh. Confira a instalação com bash --version e salve os arquivos com quebras de linha LF.
Execute as linhas abaixo na mesma sessão, em ordem, e pare se alguma falhar. Após mktemp, confirme que lab contém uma nova pasta dentro do seu diretório pessoal; só prossiga depois de cd entrar nela. Se a criação ou a mudança de pasta falhar, não execute as gravações seguintes em outro local.
lab=$(mktemp -d "$HOME/linux-script-lab.XXXXXX")
cd "$lab"
mkdir "sample files"
printf "one\n" > "sample files/alpha.txt"
printf "two\n" > "sample files/beta.txt"
Crie um script completo e executável
O bloco abaixo cria list-files.sh na pasta atual. O programa recebe um argumento, verifica se ele indica um diretório e imprime os nomes dos arquivos regulares desse diretório. O próprio programa de listagem não cria nem exclui arquivos; a preparação do exercício cria os arquivos de exemplo. A pasta nova evita sobrescrever um script que já existia.
cat > list-files.sh <<'EOF'
#!/usr/bin/env bash
if (( $# != 1 )); then
printf "Usage: %s DIRECTORY\n" "$0" >&2
exit 2
fi
directory=$1
if [[ ! -d "$directory" ]]; then
printf "Not a directory: %s\n" "$directory" >&2
exit 1
fi
count=0
for path in "$directory"/*; do
[[ -f "$path" ]] || continue
printf "%s\n" "${path##*/}"
count=$((count + 1))
done
printf "files=%s\n" "$count"
EOF
bash -n list-files.sh
bash list-files.sh "sample files"
Espere alpha.txt, beta.txt e files=2; a ordem dos nomes pode variar conforme a localidade. bash -n verifica apenas a sintaxe, sem testar caminhos, permissões ou o resultado da execução. A primeira linha, iniciada por #!, é o shebang, que indica o interpretador quando o arquivo é executado diretamente.
As aspas em <<'EOF' preservam as variáveis no texto escrito: elas serão expandidas quando o script rodar, não enquanto ele é criado. A linha final EOF deve ficar sozinha, sem espaços antes ou depois.
Entenda as variáveis e as aspas nos caminhos
Escreva uma atribuição sem espaços ao redor do sinal de igual, como directory=$1. Ao usar o valor, "$directory" mantém um caminho com espaços em um único argumento. As aspas simples preservam o texto literal; as aspas duplas permitem a expansão de parâmetros do Bash, evitando a divisão em palavras e a expansão de nomes de arquivos no resultado. Não é necessário usar eval para interpretar novamente a entrada como comando.
Em "$directory"/*, a parte do diretório fica protegida, e apenas o asterisco participa da expansão de nomes. Na configuração padrão do Bash, um padrão sem correspondências pode permanecer literal; [[ -f "$path" ]] || continue ignora essa entrada. O padrão não inclui arquivos ocultos iniciados por ponto nem percorre subdiretórios. Um link simbólico para um arquivo regular também pode passar no teste -f.
Leia argumentos, condições, repetições e estados de saída
| Sintaxe | Significado |
|---|---|
| $# / $1 | Quantidade de argumentos / primeiro argumento |
| [[ -d ... ]] | Verifica se o destino é um diretório |
| for ...; do ...; done | Executa o mesmo conjunto de comandos para cada item expandido |
| ${path##*/} | Remove o prefixo até a última barra, deixando somente o nome |
| exit 0 / 1 / 2 | Sucesso / destino inválido / uso incorreto neste exemplo |
Se o último printf for bem-sucedido, o script termina com estado 0. Os significados de 1 e 2 são convenções definidas por este programa, e não categorias universais para todos os comandos. $? contém o estado do comando imediatamente anterior; consulte-o antes de executar outro comando.
bash list-files.sh
printf "exit=%s\n" "$?"
bash list-files.sh missing-directory
printf "exit=%s\n" "$?"
chmod u+x list-files.sh
./list-files.sh "sample files"
A execução sem argumentos mostra Usage: na saída de erro e deve resultar em exit=2. O caminho inexistente mostra Not a directory: e deve resultar em exit=1. A última linha executa diretamente o programa com o diretório válido e deve listar os dois arquivos. Um estado 0 confirma o término do programa, mas este exemplo não detecta todos os problemas possíveis de leitura: ele não é uma auditoria completa de diretórios ou permissões.
Altere uma condição de cada vez e compare os resultados
- Execute
bash list-files.sh "sample files"e confirmefiles=2. - Crie apenas
gamma.txtcomprintf "three\n" > "sample files/gamma.txt"e repita a execução: a contagem deve subir para 3. - Remova somente o arquivo acrescentado com
rm -- "sample files/gamma.txt"e execute novamente para confirmar a volta a 2. - Crie
empty-directorycommkdir empty-directorye passe esse nome ao script: esperefiles=0. Compare também com o caminho inexistente e seu estado 1.
Se aparecer um erro com bash\r ou ^M depois de editar no Windows, verifique as quebras de linha. bash ARQUIVO lê o script sem exigir o bit de execução; ./ARQUIVO precisa de permissão de execução, de um interpretador válido e de um sistema de arquivos que permita executar arquivos. Antes de limpar o exercício, confira a pasta atual e não use comandos de exclusão em massa em diretórios do sistema.
Se o editor indicar CRLF, altere para LF e salve. No VS Code, use o indicador CRLF da barra de status e escolha LF. Em um ambiente com GNU sed, o bloco a seguir cria uma cópia e converte somente o list-files.sh deste exercício. Se o backup já existir, cp -i pede confirmação antes de sobrescrevê-lo; preserve uma cópia correta antes de continuar.
cp -i -- list-files.sh list-files.sh.crlf-backup
sed -i 's/\r$//' list-files.sh
bash -n list-files.sh
bash list-files.sh "sample files"
A verificação de sintaxe deve terminar com estado 0 e sem saída. Se restarem apenas os dois arquivos originais, a execução deve informar files=2. Para desfazer a conversão, confira o conteúdo do backup e restaure-o com cp -i -- list-files.sh.crlf-backup list-files.sh. Se o backup contiver CRLF, restaurá-lo também traz essas quebras de linha de volta.




