Tutorial Shell Script

O shell é um interpretador de comandos do sistema e suas operações típicas incluem manipulação de arquivos, execução de programas e impressão de texto. Ele fornece uma linguagem de programação completa, com variáveis, estruturas de controle, laços de repetição e funções.

O shell script nada mais é do que uma sequencia de comandos Linux dentro de um arquivo executável, normalmente com a extensão .sh. Os scripts shell não são compilados, são interpretados no momento de sua execução.

Primeiro script

Na primeira linha de todo script deve ser usando os caracteres #! seguindo do caminho do shell (/bin/bash) que será usado para interpretar os comandos do script. O shell mais usado atualmente é o Bash (Bourne-Again Shell). O comando completo é: #!/bin/bash. Essa string é conhecida como shebang.

A seguir temos um exemplo de um script simples que mostra todos os usuários logados e a data atual:


#!/bin/bash

echo "Usuários logados no sistema:"

w

echo "Data atual:"

date

Para testar, salve esse script com o nome de primeiro.sh e depois coloque permissão de execução no arquivo com o comando:

chmod +x primeiro.sh

Para executá-lo, digite: ./primeiro.sh

O comando echo é usando para exibir mensagem na tela do terminal. Nesse exemplo são usados os comandos "w" e "date" para mostrar os usuários logados no sistema e a data atual. O shell script ignora os espaços em branco entre linhas.

Comentários

Os comentários são usados para deixar o script mais organizado, com informações sobre os comandos e a utilidade de cada um, por exemplo:


#!/bin/bash

# Exibe mensagem mostrando os usuários logados
echo "Usuários logados no sistema:"
w

# Mostra a data atual do sistema
echo "Data atual:"
date

Com exceção da linha inicial, #!/bin/bash , todas as linhas começadas com '#' são ignoradas pelo shell, servindo apenas como comentário.

Lendo informações (input) e armazenando em variáveis:

O shell pode usar variáveis para armazenar valores digitados pelo usuário. No exemplo abaixo a função read lê um valor digitado pelo usuário e armazena na variável "nome" . Para exibir o conteúdo da variável "nome" é usado o cifrão, assim: $nome.


#!/bin/sh

echo "Qual o seu nome?"

read nome

echo "Bem vindo, $nome"

É possível colocar vários comandos em uma mesma linha, basta separá-los com um sinal de ponto e virgula (;), conforme abaixo:



#!/bin/sh

echo "Qual o seu nome?"; read nome; echo "Bem vindo, $nome"


Uma variável pode receber qualquer tipo de dado: números, string, texto, ou um nome de arquivo. O nome de uma variável pode conter apenas letras (A a Z), números (0 a 9) ou o caractere de sublinhado (_). Não podem ser usados os caracteres !, * e -. Esse caracteres tem significado especial no shell, por isso não podem ser usados.

Para atribuir um valor a uma variável é usado o sinal de igual, conforme abaixo:


nome="João"

idade=20

OBS: Não pode haver espaço antes ou depois do sinal de igual.

Além de valores, é possível armazenar a saída de outros comandos em variáveis usando o cifrão seguido de parenteses, como por exemplo:


data_atual=$(date)


Argumentos da linha de comando

Os argumentos de linha de comando são usados para passar parâmetros para o script. Dentro do script esses parâmetros são usados como variáveis, como no exemplo abaixo:


#!/bin/bash

echo "Primeiro Parâmetro: $1"
echo "Segundo Parâmetro: $2"
echo "Terceiro Parâmetro: $3"
echo "Número total de parâmetros: $#"

Os parâmetros são passados com um espaço entre eles, por exemplo:

./teste_parametros.sh 1 2 3


Variáveis especiais

Conforme foi dito anteriormente, alguns caracteres tem significado especial no shell. Eles são usados por variáveis especiais do sistema que armazenam informações sobre o script em si e também sobre o shell que esta executando o script.

Por exemplo, o comando abaixo mostra o PID (process id, ou seja, o numero do processo) do shell atual:


echo $$

Abaixo você pode ver a lista de todas as variáveis especiais e o significado de cada uma:

$! Mostra o número do processo do último comando em segundo plano.

$0 Mostra o nome do arquivo do script atual.

$1 até $9 Mostram os argumentos passados na linha de comando para o script. Por exemplo, o primeiro argumento é $1, o segundo argumento é $2 e assim por diante.

$# Mostra o total do número de argumentos passados para um script.

$* Todos os argumentos passados para um script. Se um script receber dois argumentos, $* será equivalente a $1 $2.

$? Mostra o status de saída do último comando executado. Pode ser usado para recuperar o valor retornado de uma função.


Criando um vetor ou array

Uma variável de shell é capaz de manter um único valor. O Shell suporta um tipo diferente de variável chamado de array ou vetor que pode conter vários valores ao mesmo tempo, agrupando um conjunto de variáveis. Em vez de criar um novo nome para cada variável necessária, você pode usar uma única variável que armazena todas as outras variáveis.

Para criar um array que armazena vários nomes de alunos, basta criar um nome para o array e usar um índice como referencia a cada posição do array, da seguinte forma:


nomes[0]="Laura"
nomes[1]="Beatriz"
nomes[2]="Augusto"
nomes[3]="José"
nomes[4]="Felipe"

Outra opção é declarar em sequencia cada valor do array, separados por um espaço:


nomes=(Laura Beatriz Augusto José Felipe)

Para imprimir o valor de cada posição usa-se o um par de chaves, indicando a posição:


echo ${nomes[0]}
echo ${nomes[1]}
echo ${nomes[2]}

Para mostrar na tela o valor de todo o array de uma vez usa-se o sinal de arroba como índice:


echo ${nomes[@]}


Operadores

Existem vários operadores suportados pelo shell, entre eles operadores aritméticos, relacionais, booleanos, operadores de string e teste de arquivo.

Para realizar operações aritméticas no shell é usando o cifrão seguido de dois parenteses, assim:


#!/bin/bash

resultado=$((2+2))
echo "Valor total: $resultado"

Além da soma, existem outros operados aritméticos:

Subtração:


resultado=$((2-2))

Multiplicação:


resultado=$((2*2))

Divisão:


resultado=$((2/2))

Modulo:


resultado=$((2%2))


Operadores Relacionais

Para comparar se um numero é maior, menor ou igual a outro número, o shell usa os seguintes operadores:

-eq Retorna true (verdadeiro) se o valor de dois operandos for igual.
-ne Retorna true (verdadeiro) se o valor de dois operandos não for igual.
-gt Retorna true (verdadeiro) se o valor do operando à esquerda é maior que o valor do operando da direita.
-lt Retorna true (verdadeiro) se o valor do operando à esquerda é menor que o valor do operando à direita.
-ge Retorna true (verdadeiro) se o valor do operando à esquerda é maior ou igual ao valor do operando à direita.
-le Retorna true (verdadeiro) se o valor do operando da esquerda é menor ou igual ao valor do operando da direita.

Operadores booleanos

Para fazer comparações lógicas entre duas expressões, o shell usa os seguintes operadores:

! negação lógica (NOT): inverte uma condição verdadeira em falso e vice-versa.
-o "OU" lógico (OR): se um dos operandos for verdadeiro, a condição se tornará verdadeira.
-a "E" lógico (AND): se ambos os operandos forem verdadeiros, a condição se tornará verdadeira.


Operadores de String

Para comparar duas strings, o shell usa os seguintes operadores:

== Retorna true se o valor de duas strings é igual.
!= Retorna true se o valor de duas strings for diferente.
-z Retorna true se o valor da string é nula.
-n Retorna true se o valor da string não é nula.


Operadores de Teste em Arquivos

Para testar várias propriedades de um arquivo no Linux, o shell usa os seguintes operadores:

-d Retorna true se o arquivo é um diretório.
-f Retorna true se o arquivo é um arquivo comum.
-r Retorna true se o arquivo tem permissão de leitura.
-w Retorna true se o arquivo tem permissão de gravação.
-x Retorna true se o arquivo é executável.
-s Retorna true se o arquivo tem tamanho maior que 0.
-e Retorna true se o arquivo ou diretorio existe.

Controle de fluxo if / else

Ao escrever um script pode haver uma situação em que você precisa seguir um caminho especifico caso um condição seja verdadeira.Nesse caso, você precisa usar instruções condicionais que permitam que seu programa tome decisões corretas e execute as ações especificas.

O comando if é o principal comando para fazer o controle de fluxo em um script shell. Normalmente é usado em conjunto com o else para executar somente caso a condição seja falsa, mas é opcional. A sua sintaxe é:


if [ condição ]
then
  comandos
else
  comandos
fi

Exemplo:


#!/bin/bash

echo "Digite a senha:"

read  senha

if [ $senha == "12345" ]
then
    echo "Senha correta!"
else
    echo "Senha errada!"
fi

Você pode ter vários comandos if aninhados, como no exemplo abaixo:


#!/bin/bash

echo "Digite um número:"

read numero

if [ $numero -gt 0 ]; then
  echo "O número é positivo."
elif [ $numero -lt 0 ]
then
  echo "O número é negativo."
elif [ $numero -eq 0 ]
then
  echo "O número é zero."

fi


Controle de Fluxo com o case

Quando for necessário incluir vários if, existe um alternativa mais elegante que é comando case. Ele permite que você verifique se a condição é verdadeira e execute um ou mais comandos correspondentes. Além disso, existe uma ultima condição dentro do case que é executada caso nenhuma outra correspondência seja encontrada. Abaixo temos um exemplo do uso do case:


case  $variavel  in
     condicao1)  
        comandos                                  
     ;;
     condicao2)
        comandos          
     ;;      
     condicao3)  
        comandos              
     ;;
     *) comando caso todas condições sejam falsas       
esac

Exemplo:


#!/bin/bash
  echo "Escolha uma opção:"
  echo "1 - Usuarios logados no sistema"
  echo "2 - Espaço em disco"
  echo "3 - Mostrar memória livre"                                                
 read opcao;
  case $opcao in
   1)
        echo "Usuarios logados:"   
        w

      ;;

   2)
        echo "Espaco em disco:"    
        df -h

   ;;

   3)
        echo "Memoria livre:"  
        free -m

  ;;
   *) echo "Opção não encontrada"

esac


Laços de repetição (loops)

Um loop é uma poderosa ferramenta de programação que permite executar um conjunto de comandos repetidamente. O shell suporta os seguintes laços de repetição: while, for e until.

Cado tipo de loop é indicado para uma situação, por exemplo, o while executa os comandos enquanto uma condição seja verdadeira. O for, executa um laço por uma quantidade pré-determinada de vezes.

while:

#!/bin/bash

a=0

# Enquanto a variavel "a" for menor que 10,
# mostra o valor de "a"

while [ $a -lt 10 ]
do
   a=$(($a+1))

   echo  $a
done

for:

#!/bin/bash
 echo “Mostra números de 1 a 10”
 for n in {1..10};
 do
   echo $n
 done

É possivel gerar sequencias usando o comando "seq" conforme abaixo:


#!/bin/bash
 echo “Mostra números de 1 a 100”
 for n in $(seq 1 100);
 do
  echo $n
done

Until:

#!/bin/bash

a=0

# Enquanto a variavel "a" não for maior que 10,
# mostra o valor de "a"

until [ $a -gt 10 ]
do
   echo $a
   a=$(($a+1))
done





Funções

As funções permitem que você divida a trecho de codigo em subseções lógicas menores, que podem ser chamadas para executar suas tarefas individuais quando necessário. Isso evita a repetição de codigo e deixa o script mais organizado.

Para declarar uma função, basta usar a seguinte sintaxe:


nome_da_função() {

    comandos

}

O nome da sua função é pode ser qualquer um, seguindo as mesmas regras para criação de variaveis. Depois de declarar a função, basta chama-la pelo nome, sem usar o parenteses, por exemplo:


#!/bin/bash

# Criar uma função

mensagem() {
   echo "Primeira função em shell script !"
}

# Chamar a função

mensagem