Verifique se existe um diretório em um script de shell

Qual comando pode ser usado para verificar se um diretório existe ou não, dentro de um script de shell?

Para verificar se existe um diretório em um script de shell, você pode usar o seguinte:

if [ -d "$DIRECTORY" ]; then # Control will enter here if $DIRECTORY exists. fi 

Ou para verificar se um diretório não existe:

 if [ ! -d "$DIRECTORY" ]; then # Control will enter here if $DIRECTORY doesn't exist. fi 

No entanto, como Jon Ericson aponta, os comandos subseqüentes podem não funcionar como planejado se você não levar em conta que um link simbólico para um diretório também passará esta verificação. Por exemplo, executando isso:

 ln -s "$ACTUAL_DIR" "$SYMLINK" if [ -d "$SYMLINK" ]; then rmdir "$SYMLINK" fi 

Irá produzir a mensagem de erro:

 rmdir: failed to remove `symlink': Not a directory 

Portanto, os links simbólicos podem ter que ser tratados de maneira diferente, se comandos subsequentes esperarem diretórios:

 if [ -d "$LINK_OR_DIR" ]; then if [ -L "$LINK_OR_DIR" ]; then # It is a symlink! # Symbolic link specific commands go here. rm "$LINK_OR_DIR" else # It's a directory! # Directory command goes here. rmdir "$LINK_OR_DIR" fi fi 

Tome nota particular das aspas duplas usadas para envolver as variables, a razão para isso é explicada por 8jean em outra resposta .

Se as variables ​​contiverem espaços ou outros caracteres incomuns, isso provavelmente causará falha no script.

Lembre-se de sempre envolver as variables ​​entre aspas quando fizer referência a elas em um script bash. As crianças crescem com a ideia de que podem ter espaços e muitos outros personagens engraçados em seus nomes de diretório. (Espaços! De volta aos meus dias, não tínhamos espaços extravagantes!;))

Um dia, uma dessas crianças executará seu script com $DIRECTORY definido como "My M0viez" e seu script será "My M0viez" . Você não quer isso. Então use isso.

 if [ -d "$DIRECTORY" ]; then # Will enter here if $DIRECTORY exists, even if it contains spaces fi 

Observe que o teste -d pode produzir alguns resultados surpreendentes:

 $ ln -s tmp/ t $ if [ -dt ]; then rmdir t; fi rmdir: directory "t": Path component not a directory 

Arquivo abaixo: “Quando um diretório não é um diretório?” A resposta: “Quando é um link simbólico para um diretório”. Um teste um pouco mais completo:

 if [ -dt ]; then if [ -L t ]; then rm t else rmdir t fi fi 

Você pode encontrar mais informações no manual de Bash sobre expressões condicionais Bash e o comando [ builtin e o comando [[ compound commmand] .

Eu acho que a versão do test dois colchetes faz com que os testes lógicos de escrita sejam mais naturais:

 if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then echo "It's a bona-fide directory" fi 

Forma mais curta:

 [ -d "$DIR" ] && echo "Yes" 

Para verificar se existe um diretório, você pode usar a estrutura if simples assim:

 if [ -d directory/path to a directory ] ; then #Things to do else #if needed #also: elif [new condition] # things to do fi 

Você pode fazer isso também em negativo

 if [ ! -d directory/path to a directory ] ; then # things to do when not an existing directory 

Nota : Tenha cuidado, deixe espaços vazios em ambos os lados das chaves de abertura e fechamento.

Com a mesma syntax você pode usar:

 -e: any kind of archive -f: file -h: symbolic link -r: readable file -w: writable file -x: executable file -s: file size greater than zero 
 if [ -d "$DIRECTORY" ]; then # Here if $DIRECTORY exists fi 

Você pode usar o test -d (veja man test ).

-d file Verdadeiro se o arquivo existir e for um diretório.

Por exemplo:

 test -d "/etc" && echo Exists || echo Does not exist 

Nota: O comando test é o mesmo que a expressão condicional [ (veja: man [ ), portanto, é portável através de scripts de shell.

[ – Este é um sinônimo para o test embutido, mas o último argumento deve ser literal ] , para coincidir com a abertura [ .

Para possíveis opções ou ajuda adicional, verifique:

  • help [
  • help test
  • man test ou man [

Ou para algo completamente inútil:

 [ -d . ] || echo "No" 

Aqui está uma expressão muito pragmática:

 (cd $dir) || return # is this a directory, # and do we have access? 

Eu normalmente envolvo em uma function:

 can_use_as_dir() { (cd ${1:?pathname expected}) || return } 

Ou:

 assert_dir_access() { (cd ${1:?pathname expected}) || exit } 

O bom dessa abordagem é que não preciso pensar em uma boa mensagem de erro.

cd vai me dar uma mensagem de uma linha padrão para stderr já. Ele também dará mais informações do que eu poderei fornecer. Ao executar o cd dentro de um subshell ( ... ) , o comando não afeta o diretório atual do chamador. Se o diretório existir, essa subshell e a function são apenas um não operacional.

Em seguida é o argumento que passamos para o cd : ${1:?pathname expected} . Esta é uma forma mais elaborada de substituição de parâmetros, que é explicada em mais detalhes abaixo.

Tl; dr: Se a string passada para esta function está vazia, novamente saímos da subshell ( ... ) e retornamos da function com a mensagem de erro dada.


Citando a página man do ksh93 :

 ${parameter:?word} 

Se o parameter estiver definido e não for nulo, substitua seu valor; caso contrário, imprima a word e saia do shell (se não for interativo). Se a word for omitida, uma mensagem padrão será impressa.

e

Se os dois pontos : forem omitidos das expressões acima, o shell só verificará se o parâmetro está definido ou não.

O fraseado aqui é peculiar à documentação do shell, pois a word pode se referir a qualquer string razoável, incluindo espaço em branco.

Neste caso em particular, eu sei que a mensagem de erro padrão 1: parameter not set é suficiente, então eu amplio o tipo de valor que esperamos aqui – o pathname do pathname de um diretório.

Uma nota filosófica: O shell não é uma linguagem orientada a objects, então a mensagem diz pathname , não directory . Nesse nível, eu prefiro manter isso simples – os argumentos para uma function são apenas strings.

 if [ -d "$Directory" -a -w "$Directory" ] then #Statements fi 

O código acima verifica se o diretório existe e se é gravável.

Digite este código no bash promt

 if [ -d "$DIRECTORY" ]; then # if true this block of code will execute fi 

Na verdade, você deve usar várias ferramentas para obter uma abordagem à prova de balas:

 DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing echo "It's a dir"; fi 

Não precisa se preocupar com espaços e caracteres especiais, desde que você use "${}" .

Note que [[]] não é tão portátil quanto [] , mas como a maioria das pessoas trabalha com versões modernas do Bash (já que a maioria das pessoas nem trabalha com a linha de comando :-p), o benefício é maior que o problema.

Mais resources usando o find

  • Verificar a existência da pasta nos subdiretórios:

     found=`find -type d -name "myDirectory"` if [ -n "$found"] then # The variable 'found' contains the full path where "myDirectory" is. # It may contain several lines if there are several folders named "myDirectory". fi 
  • Verificar a existência de uma ou várias pastas com base em um padrão dentro do diretório atual:

     found=`find -maxdepth 1 -type d -name "my*"` if [ -n "$found"] then # The variable 'found' contains the full path where folders "my*" have been found. fi 
  • Ambas as combinações. No exemplo a seguir, ele verifica a existência da pasta no diretório atual:

     found=`find -maxdepth 1 -type d -name "myDirectory"` if [ -n "$found"] then # The variable 'found' is not empty => "myDirectory"` exists. fi 
  1. Um script simples para testar se dir ou arquivo está presente ou não:

     if [ -d /home/ram/dir ] # for file "if [-f /home/rama/file]" then echo "dir present" else echo "dir not present" fi 
  2. Um script simples para verificar se o diretório está presente ou não:

     mkdir tempdir # if you want to check file use touch instead of mkdir ret=$? if [ "$ret" == "0" ] then echo "dir present" else echo "dir not present" fi 

    Os scripts acima irão verificar se o diretório está presente ou não

    $? se o último comando sucess ele retorna “0” senão valor diferente de zero. suponha tempdir já está presente, em seguida, mkdir tempdir dará erro como abaixo:

    mkdir: não é possível criar o diretório ‘tempdir’: o arquivo existe

Para verificar mais de um diretório, use este código:

 if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then # Things to do fi 

Você já pensou em fazer o que quiser no if vez de olhar antes de pular?

IE, se você quiser verificar a existência de um diretório antes de inseri-lo, tente fazer isso:

 if pushd /path/you/want/to/enter; then # commands you want to run in this directory popd fi 

Se o caminho que você der ao pushd existir, você o pushd e sairá com 0 , o que significa que a parte da instrução será executada. Se não existir, nada acontecerá (além de alguma saída dizendo que o diretório não existe, o que provavelmente é um efeito colateral útil de qualquer forma para debugging).

Parece melhor que isso, o que requer que você se repita:

 if [ -d /path/you/want/to/enter ]; then pushd /path/you/want/to/enter # commands you want to run in this directory popd fi 

A mesma coisa funciona com cd , mv , rm , etc … se você experimentá-los em arquivos que não existem, eles sairão com um erro e imprimirão uma mensagem dizendo que ele não existe, e o seu bloco será ignorado. Se você experimentá-los em arquivos que existem, o comando será executado e sairá com um status 0 , permitindo que seu bloco seja executado.

 [[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link" 

NB: cotar variables ​​é uma boa prática.

Verifique se o diretório existe, senão faça um

 [ -d "$DIRECTORY" ] || mkdir $DIRECTORY 
 [ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST" 

Esta resposta foi embrulhada como um script de shell

Exemplos

 $ is_dir ~ YES $ is_dir /tmp YES $ is_dir ~/bin YES $ mkdir '/tmp/test me' $ is_dir '/tmp/test me' YES $ is_dir /asdf/asdf NO # Example of calling it in another script DIR=~/mydata if [ $(is_dir $DIR) == "NO" ] then echo "Folder doesnt exist: $DIR"; exit; fi 

is_dir

 function show_help() { IT=$(CAT <  

Usando a verificação -e irá verificar os arquivos e isso inclui diretórios.

 if [ -e ${FILE_PATH_AND_NAME} ] then echo "The file or directory exists." fi 

Conforme comentário de Jonathan :

Se você quer criar o diretório e ele ainda não existe, então a técnica mais simples é usar o mkdir -p que cria o diretório – e todos os diretórios ausentes no caminho – e não falha se o diretório já existir, então você pode faça tudo de uma vez com:

 mkdir -p /some/directory/you/want/to/exist || exit 1 
 if [ -d "$DIRECTORY" ]; then # Will enter here if $DIRECTORY exists fi 

Isso não é totalmente verdade … Se você quiser ir para esse diretório, você também precisa ter os direitos de execução no diretório. Talvez você precise ter direitos de gravação também.

Portanto:

 if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then # ... to go to that directory (even if DIRECTORY is a link) cd $DIRECTORY pwd fi 

 if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then # ... to go to that directory and write something there (even if DIRECTORY is a link) cd $DIRECTORY touch foobar fi 

O comando ls em conjunto com a opção -l (listview longa) retorna informações de atributos sobre arquivos e diretórios.
Em particular, o primeiro caractere da saída ls -l é geralmente um d ou um - (traço). No caso de um d o listado é um diretório com certeza.

O comando a seguir em apenas uma linha dirá se a variável ISDIR determinada contém um caminho para um diretório ou não:

 [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && echo "YES, $ISDIR is a directory." || echo "Sorry, $ISDIR is not a directory" 

Uso prático:

  [claudio@nowhere ~]$ ISDIR="$HOME/Music" [claudio@nowhere ~]$ ls -ld "$ISDIR" drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && echo "YES, $ISDIR is a directory." || echo "Sorry, $ISDIR is not a directory" YES, /home/claudio/Music is a directory. [claudio@nowhere ~]$ touch "empty file.txt" [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && echo "YES, $ISDIR is a directory." || echo "Sorry, $ISDIR is not a directoy" Sorry, /home/claudio/empty file.txt is not a directory 
 file="foo" if [[ -e "$file" ]]; then echo "File Exists"; fi; 

Se você quiser verificar se existe um diretório, independentemente de ser um diretório real ou um symlink, use isto:

 ls $DIR if [ $? != 0 ]; then echo "Directory $DIR already exists!" exit 1; fi echo "Directory $DIR does not exist..." 

Explicação: O comando “ls” dá um erro “ls: / x: Nenhum arquivo ou diretório” se o diretório ou link simbólico não existe, e também define o código de retorno, que você pode recuperar via “$?”, Para não -null (normalmente “1”). Certifique-se de verificar o código de retorno diretamente após chamar “ls”.

(1)

 [ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists" 

(2)

 [ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists" 

(3)

 [[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists" 

Se encontrou um problema com uma das abordagens fornecidas acima.

Com o comando ls ; os casos em que o diretório não existe – uma mensagem de erro é mostrada

$ [[ ls -ld SAMPLE_DIR| grep ^d | wc -l ls -ld SAMPLE_DIR| grep ^d | wc -l ls -ld SAMPLE_DIR| grep ^d | wc -l -eq 1]] && echo existe || não existe -ksh: não: não encontrado [Nenhum arquivo ou diretório]

Grandes soluções por aí, mas em última análise, todo script falhará se você não estiver no diretório correto. Então codifique como este:

 if [ -d "$LINK_OR_DIR" ]; then if [ -L "$LINK_OR_DIR" ]; then # It is a symlink! # Symbolic link specific commands go here rm "$LINK_OR_DIR" else # It's a directory! # Directory command goes here rmdir "$LINK_OR_DIR" fi fi 

executará com sucesso somente se no momento da execução você estiver em um diretório que tenha um subdiretório que você verifique.

Eu entendo a pergunta inicial assim: para verificar se existe um diretório independente da posição do usuário no sistema de arquivos. Então, usando o comando ‘find’ pode fazer o truque:

 dir=" " echo "Input directory name to search for:" read dir find $HOME -name $dir -type d 

Essa solução é boa porque permite o uso de caracteres curinga, um recurso útil na pesquisa de arquivos / diretórios. O único problema é que, se o diretório pesquisado não existir, o comando ‘find’ não imprimirá nada para stdout (não é uma solução elegante para o meu gosto) e terá, no entanto, uma saída zero. Talvez alguém possa melhorar isso.

Abaixo do achado pode ser usado,

 find . -type d -name dirname -prune -print