Como verificar se existe um arquivo em scripts Bash do Linux

Publicados: 2022-08-18
Laptop Linux mostrando um prompt bash
fatmawati achmad zaenuri/Shutterstock.com

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.

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.

RELACIONADO: Como usar testes condicionais de colchete duplo no Linux

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 conjunto de permissões setgid ( 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 conjunto de permissões setuid ( 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 teste -a foi descontinuado e substituído pelo teste -e .

RELACIONADO: Como usar SUID, SGID e Sticky Bits no Linux

Usando os testes em scripts

O arquivo genérico test if é uma construção de script simples. A comparação dentro dos colchetes duplos ” [[ ]] ” usa o teste -f 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 

Fazendo um script executável com chmod

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 

Executando script1.sh em um arquivo normal

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 

Executando script1.sh em um arquivo que não existe

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 sinalizador -f 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 

Executando script1.sh em um arquivo de dispositivo

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 

Executando script2.sh em um arquivo de dispositivo de caractere

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 

Executando scrip2.sh em um arquivo de dispositivo de bloco

Podemos fazer uso do operador lógico OR 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 

script3.sh manipulando corretamente os arquivos de dispositivo de caracteres e blocos

Se for importante para você diferenciar entre os diferentes tipos de arquivos de dispositivo, você pode usar instruções if 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 

script8.sh identificando corretamente os arquivos de caracteres e dispositivos de bloco

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 ao root .

 ./script5.sh .bashrc
 ./script5.sh /etc/fstab 

script5.sh verificando se existe um arquivo e se as permissões de leitura e gravação estão definidas

Para testar a existência de um diretório, use o teste -d . 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 operador lógico NOT ! no teste de instrução if .

 #!/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 verificaremos com ls e a opção -d (diretório) se o diretório de backup existe.

 ./script6.sh Documentos/project-backup
 ls -d Documentos/backup do projeto 

script6.sh detectando se existe um diretório

O diretório de backup foi criado. Se executarmos o script novamente, ele deverá informar que o diretório já está presente.

 ./script6.sh 

script6.sh reutilizando um diretório existente

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.

RELACIONADO: Como permitir que scripts do Linux detectem que estão sendo executados em máquinas virtuais