Se um script Linux Bash depende da presença de determinados arquivos ou diretórios, ele não pode simplesmente assumir que sim. Ele precisa verificar se eles estão definitivamente presentes. Veja como fazer isso.
Índice
Não assuma nada
Quando você está escrevendo um script, você não pode fazer suposições sobre o que está e o que não está presente em um computador. Isso é duplamente verdadeiro se o script for distribuído e executado em muitos computadores diferentes. Mais cedo ou mais tarde, o script será executado em um computador que não atende às suas suposições e falhará ou será executado de forma imprevisível.
Tudo o que valorizamos ou criamos em um computador é armazenado em um arquivo de algum formato, e todos esses arquivos residem em um diretório . Os scripts podem ler, escrever, renomear, excluir e mover arquivos e diretórios — tudo o que você pode fazer na linha de comando.
A vantagem que você tem como humano é que você pode ver o conteúdo de um diretório e saber se um arquivo existe ou não – ou se o diretório esperado existe. Se um script falhar ao manipular arquivos, pode ter resultados sérios e prejudiciais.
O Bash fornece um conjunto abrangente de testes que você pode usar para detectar arquivos e diretórios e testar muitos de seus atributos. Incorporá-los em scripts é fácil, mas os benefícios em termos de robustez e controle fino são consideráveis.
A gama de testes
Ao combinar a instrução if com o teste apropriado de uma grande coleção de testes de arquivos e diretórios, podemos determinar facilmente se um arquivo existe, se é executável ou gravável e muito mais.
- -b : Retorna verdadeiro se o arquivo for um arquivo especial de bloco.
- -c : Retorna verdadeiro se o arquivo for um caractere especial.
- -d : Retorna verdadeiro se o “arquivo” for um diretório.
- -e : Retorna verdadeiro se o arquivo existir.
- -f : Retorna verdadeiro se o arquivo existir e for um arquivo normal.
- -g : Retorna verdadeiro se o arquivo tiver o
setgid
conjunto de permissões (chmod g+
). - -h : Retorna true se o arquivo for um link simbólico .
- -L : Retorna verdadeiro se o arquivo for um link simbólico.
- -k : Retorna verdadeiro se tiver seu bit fixo definido (
chmod +t
). - -p : Retorna true se o arquivo for um pipe nomeado.
- -r : Retorna verdadeiro se o arquivo for legível.
- -s : Retorna verdadeiro se os arquivos existirem e não estiverem vazios.
- -S : Retorna verdadeiro se o arquivo for um soquete.
- -t : Retorna verdadeiro se o descritor de arquivo for aberto em um terminal.
- -u : Retorna verdadeiro se o arquivo tiver o
setuid
conjunto de permissões (chmod u+
). - -w : Retorna true se o arquivo for gravável.
- -x : Retorna true se o arquivo for executável.
- -O : Retorna verdadeiro se for de sua propriedade.
- -G : Retorna verdadeiro se for de propriedade do seu grupo.
- -N : Retorna verdadeiro se o arquivo foi modificado desde a última leitura.
- ! : O operador lógico NOT.
- && : O operador lógico AND.
- || : O operador lógico OR.
A lista começa com -b
porque o -a
teste foi descontinuado e substituído pelo -e
teste.
Usando os testes em scripts
A instrução de teste de arquivo genérico if
é uma construção de script simples. A comparação entre colchetes duplos ” [[ ]]
” usa o -f
teste para determinar se existe um arquivo regular com esse nome.
Copie o texto deste script em um editor e salve-o em um arquivo chamado “script1.sh”, e use chmod
para torná-lo executável .
#!/bin/bash se [[ -f $1 ]] então echo "O arquivo $1 existe." senão echo "O arquivo $1 não pode ser encontrado." fi
Você tem que passar o nome do arquivo para o script na linha de comando.
chmod +x script1.sh
Você precisará fazer isso com cada script se quiser experimentar os outros exemplos do artigo.
Vamos tentar o script em um arquivo de texto simples.
./script1.sh arquivo-teste.txt
O arquivo existe e o script relata corretamente esse fato. Se excluirmos o arquivo e tentarmos novamente, o teste deverá falhar e o script deverá relatar isso para nós.
./script1.sh arquivo-teste.txt
Em uma situação da vida real, seu script precisaria tomar qualquer ação apropriada. Talvez ele sinalize o erro e pare. Talvez ele crie o arquivo e continue. Ele pode copiar algo de um diretório de backup para substituir o arquivo ausente. Tudo depende do objetivo do roteiro. Mas pelo menos agora o script é capaz de tomar a decisão com base em saber se o arquivo está presente ou não.
O -f
sinalizador testa se o arquivo está presente e é um arquivo “regular”. Em outras palavras, não é algo que parece ser um arquivo, mas não é, como um arquivo de dispositivo.
Usaremos ls para verificar se o arquivo “/dev/random” existe, e então veremos o que o script faz dele.
ls -lh /dev/random
./script /dev/random
Como nosso script está testando arquivos regulares e “/dev/random” é um arquivo de dispositivo , o teste falha. Muitas vezes, para saber se um arquivo existe, você precisa escolher cuidadosamente qual teste usar ou usar vários testes.
Este é o “script2.sh”, que testa arquivos regulares e arquivos de dispositivos de caracteres.
#!/bin/bash se [[ -f $1 ]] então echo "O arquivo $1 existe." senão echo "O arquivo $1 está faltando ou não é um arquivo normal." fi se [[ -c $1]] então echo "O arquivo $1 é um arquivo de dispositivo de caractere." senão echo "O arquivo $1 está faltando ou não é um arquivo especial." fi
Se executarmos este script no arquivo de dispositivo “/dev/random”, o primeiro teste falhará, o que esperamos, e o segundo teste será bem-sucedido. Ele reconhece o arquivo como um arquivo de dispositivo.
./script2.sh /dev/random
Na verdade, ele o reconhece como um arquivo de dispositivo de caractere . Alguns arquivos de dispositivo são arquivos de dispositivo de bloco. Do jeito que está, nosso script não vai lidar com isso.
./script2.sh /dev/sda
Podemos fazer uso do OR
operador lógico e incluir outro teste na segunda instrução if. Desta vez, se o arquivo for um arquivo de dispositivo de caractere ou um arquivo de dispositivo de bloco, o teste retornará verdadeiro. Este é “script3.sh.”
#!/bin/bash se [[ -f $1 ]] então echo "O arquivo $1 existe." senão echo "O arquivo $1 está faltando ou não é um arquivo normal." fi if [[ -c $1 || -b $ 1 ]] então echo "O arquivo $1 é um arquivo de dispositivo de caractere ou bloco." senão echo "O arquivo $1 está faltando ou não é um arquivo especial." fi
Este script reconhece os arquivos de dispositivo de caractere e de dispositivo de bloco.
./script3.sh /dev/random
./script3.sh /dev/sda
Se for importante para você diferenciar entre os diferentes tipos de arquivos de dispositivo, você pode usar if
instruções aninhadas. Este é “script4.sh.”
#!/bin/bash se [[ -f $1 ]] então echo "O arquivo $1 existe." senão echo "O arquivo $1 está faltando ou não é um arquivo normal." fi se [[ -c $1]] então echo "O arquivo $1 é um arquivo de dispositivo de caractere." senão se [[ -b $1 ]] então echo "O arquivo $1 é um arquivo de dispositivo de bloco." senão echo "O arquivo $1 está ausente ou não é um arquivo de dispositivo." fi fi
Este script reconhece e categoriza os arquivos de dispositivo de caractere e de dispositivo de bloco.
./script4.sh /dev/random
./script4.sh /dev/sda
Usando o operador lógico AND, podemos testar várias características de uma só vez. Este é “script5.sh.” Ele verifica se existe um arquivo e se o script possui permissões de leitura e gravação para ele.
#!/bin/bash if [[ -f $1 && -r $1 && -w $1]] então echo "O arquivo $1 existe e temos permissões de leitura/gravação." senão echo "O arquivo $1 está faltando, não é um arquivo normal, ou não podemos ler/gravar nele." fi
Executaremos o script em um arquivo que pertence a nós e um que pertence a root
.
./script5.sh .bashrc
./script5.sh /etc/fstab
Para testar a existência de um diretório, use o -d
teste. Este é “script6.sh.” Faz parte de um script de backup. A primeira coisa que faz é verificar se o diretório passado na linha de comando existe ou não. Ele usa o NOT
operador lógico !
no if
teste de instrução.
#!/bin/bash E se [[ ! -d $ 1 ]] então echo "Criando diretório de backup:" $1 mkdir $1 E se [[ ! $? -eq 0 ]] então echo "Não foi possível criar o diretório de backup:" $1 saída fi senão echo "O diretório de backup existe." fi # continua com backup de arquivos echo "Fazendo backup para: "$1
Se o diretório não existir, ele o cria. Se os arquivos de criação do diretório, o script é encerrado. Se a criação do diretório for bem-sucedida ou o diretório já existir, o script continuará com suas ações de backup.
Executaremos o script e, em seguida, verificaremos com ls
e a -d
opção (diretório) se o diretório de backup existe.
./script6.sh Documentos/project-backup
ls -d Documentos/backup do projeto
O diretório de backup foi criado. Se executarmos o script novamente, ele deverá informar que o diretório já está presente.
./script6.sh
O script encontra o diretório e segue em frente para realizar o backup.
Teste, não assuma
Mais cedo ou mais tarde, suposições levarão a coisas ruins acontecendo. Teste primeiro e reaja de acordo.
Conhecimento é poder. Use testes para dar aos seus scripts o conhecimento de que eles precisam.