Qual comando pode ser usado para verificar se um diretório existe ou não, dentro de um script de shell Bash?
Qual comando pode ser usado para verificar se um diretório existe ou não, dentro de um script de shell Bash?
Respostas:
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á nessa 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 das aspas duplas usadas para agrupar as variáveis. A razão para isso é explicada por 8jean em outra resposta .
Se as variáveis contiverem espaços ou outros caracteres incomuns, provavelmente o script falhará.
[ ! -d "$DIRECTORY" ]
será verdade tanto se $DIRECTORY
não existe, ou se faz existir, mas não é um diretório. Considere algo como if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; isso falhará se "$DIRECTORY"
for um arquivo. (Claro que você deve verificar se mkdir
conseguiu qualquer maneira, há uma série de razões que podem falhar.)
-d
) e o link simbólico ( -L
), é mais fácil acrescentar uma barra à variável, como if [ -d "${THING:+$THING/}" ]
. Um diretório não se importará com a barra extra. Um arquivo será avaliado como falso. Vazio permanecerá vazio, tão falso. E um link simbólico será resolvido para o seu destino. Claro, isso depende do seu objetivo. Se você quiser ir para lá, tudo bem. Se você deseja excluí-lo , o código nesta resposta é melhor.
Lembre-se de sempre agrupar variáveis entre aspas duplas ao fazer referência a elas em um script Bash. Hoje em dia, 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! Nos meus dias, não tínhamos espaços elegantes!;))
Um dia, uma dessas crianças executará seu script com $DIRECTORY
definido como "My M0viez"
e seu script explodirá. 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 [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory
Arquivo em: "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 [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
Você pode encontrar mais informações no manual do Bash sobre expressões condicionais do Bash e o [
comando builtin e o comando [[
composto .
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... ou, por um comando que funciona em ambos os links e diretórios:rm -r tmpdir
Acho que a versão de colchete duplotest
torna os testes lógicos de escrita mais naturais:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
if [[ -d "$TARFILE" ]]
eu estou recebendo [[: not found
[[ ]]
é suportado, mas na verdade não fornece nenhuma funcionalidade diferente [ ]
. Se a portabilidade for uma preocupação, atenha-se [ ]
e use as soluções alternativas necessárias.
Forma mais curta:
[ -d "$DIR" ] && echo "Yes"
if $dir is a dir, then echo "yes"
:? Um pouco de explicação ajudaria :)
cmd && other
é uma abreviação comum para if cmd; then other; fi
- funciona com a maioria das linguagens de programação que suportam lógica booleana e é conhecida como avaliação de curto-circuito .
set -e
(que é uma prática recomendada de programação de shell ).
[ -d "$DIR" ]
é verificado (seguido por && echo Yes
), então acredito set -e
que não faz diferença para o comportamento do script (ou seja, se o teste falhar, o script continuará normalmente).
Para verificar se existe um diretório, você pode usar uma if
estrutura simples como esta:
if [ -d directory/path to a directory ] ; then
# Things to do
else #if needed #also: elif [new condition]
# Things to do
fi
Você também pode fazer isso de forma negativa:
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 sintaxe, 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
Um script simples para testar se um diretório 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
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 verificarão se o diretório está presente ou não
$?
se o último comando for um sucesso, ele retornará "0", caso contrário, um valor diferente de zero. Suponha que tempdir
já esteja presente. Em seguida, mkdir tempdir
ocorrerá um erro como abaixo:
mkdir: não é possível criar o diretório 'tempdir': o arquivo existe
Você pode usar test -d
(ver 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 test
comando é o mesmo que a expressão condicional [
(consulte man [
:), portanto, é portátil nos scripts de shell.
[
- Este é um sinônimo para otest
builtin, mas o último argumento deve ser literal]
, para corresponder à abertura[
.
Para opções possíveis ou ajuda adicional, verifique:
help [
help test
man test
ou man [
Ou para algo completamente inútil:
[ -d . ] || echo "No"
Aqui está um idioma muito pragmático:
(cd $dir) || return # Is this a directory,
# and do we have access?
Normalmente, envolvo-o em uma função:
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
já me dará uma mensagem padrão de uma linha para erro padrão . Também fornecerá mais informações do que poderei fornecer. Ao executar cd
um subshell interno ( ... )
, o comando não afeta o diretório atual do chamador. Se o diretório existir, esse subshell e a função serão apenas não opcionais.
Em seguida é o argumento de que passamos para cd
: ${1:?pathname expected}
. Essa é uma forma mais elaborada de substituição de parâmetro, explicada em mais detalhes abaixo.
Tl; dr: Se a string passada para esta função estiver vazia, sairemos novamente do subshell ( ... )
e retornaremos da função com a mensagem de erro fornecida.
Citando a partir da ksh93
página de manual:
${parameter:?word}
Se
parameter
estiver definido e for não nulo, substitua seu valor; caso contrário, imprimaword
e saia do shell (se não for interativo). Seword
for omitido, uma mensagem padrão será impressa.
e
Se os dois pontos
:
forem omitidos das expressões acima, o shell verificará apenas se o parâmetro está definido ou não.
O fraseado aqui é peculiar à documentação do shell, como word
pode se referir a qualquer cadeia razoável, incluindo espaço em branco.
Nesse caso em particular, eu sei que a mensagem de erro padrão 1: parameter not set
não é suficiente, então amplio o tipo de valor que esperamos aqui - opathname
de um diretório.
Uma nota filosófica:
O shell não é uma linguagem orientada a objetos; portanto, a mensagem diz que pathname
não directory
. Nesse nível, prefiro mantê-lo simples - os argumentos para uma função são apenas strings.
test -d
como o @Grundlefleck explicou.
test -d /unreadable/exists
falhará, mesmo se o argumento existir.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
O código acima verifica se o diretório existe e se é gravável.
DIRECTORY=/tmp
if [ -d "$DIRECTORY" ]; then
echo "Exists"
fi
space
depois [
-> [ `` -d . Eu tenho erro por falta de espaço
Digite este código no prompt do Bash:
if [ -d "$DIRECTORY" ]; then
# If true this block of code will execute
fi
find
Verifique 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
Verifique a existência de uma ou várias pastas com base em um padrão no 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
find -maxdepth 1 -type d -name 'pattern'
. Você se importa se eu acrescentar em sua resposta esse truque? Cheers;)
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 há necessidade de se preocupar com espaços e caracteres especiais, desde que você use "${}"
.
Observe que [[]]
não é tão portátil quanto []
, mas como a maioria das pessoas trabalha com versões modernas do Bash (pois, afinal, a maioria das pessoas nem trabalha com a linha de comando :-p), o benefício é maior que o problema.
Você já pensou em fazer o que quiser no if
lugar de olhar antes de saltar?
Ou seja, se você deseja verificar a existência de um diretório antes de inseri-lo, tente fazer o seguinte:
if pushd /path/you/want/to/enter; then
# Commands you want to run in this directory
popd
fi
Se o caminho que você der pushd
existir, você o entrará e sairá com 0
, o que significa que a then
parte da instrução será executada. Se não existir, nada acontecerá (exceto alguma saída dizendo que o diretório não existe, o que provavelmente é um efeito colateral útil para a depuração).
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 vão sair com um erro e imprimir uma mensagem dizendo que não existe, e seu then
bloco será ignorado. Se você experimentá-los em arquivos que existem, o comando será executado e sairá com um status de 0
, permitindo que seu then
bloco seja executado.
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
Nota: citar variáveis é uma boa prática.
Explicação:
-d
: verifique se é um diretório-L
: verifique se é um link simbólicoPara verificar mais de um diretório, use este código:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
Verifique se o diretório existe, ou faça um:
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
mkdir -p "$DIRECTORY"
para o mesmo efeito.
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Esta resposta foi embrulhada como um script de shell
$ 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
function show_help()
{
IT=$(CAT <<EOF
usage: DIR
output: YES or NO, depending on whether or not the directory exists.
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
DIR=$1
if [ -d $DIR ]; then
echo "YES";
exit;
fi
echo "NO";
O uso da -e
verificação verificará arquivos e isso inclui diretórios.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
De acordo com o comentário de Jonathan :
Se você deseja criar o diretório e ele ainda não existe, 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, para que você possa fazer tudo isso. 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
Isto não é completamente verdadeiro...
Se você deseja acessar esse diretório, 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
Use o file
programa. Considerando que todos os diretórios também são arquivos no Linux, emitir o seguinte comando seria suficiente:
file $directory_name
Verificando um arquivo inexistente: file blah
Resultado: cannot open 'blah' (No such file or directory)
Verificando um diretório existente: file bluh
Resultado: bluh: directory
O ls
comando em conjunto com a opção -l
(lista longa) retorna informações de atributos sobre arquivos e diretórios.
Em particular, o primeiro caractere de ls -l
saída é 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 informará se a ISDIR
variável especificada 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ê deseja verificar se existe um diretório, independentemente de ser um diretório real ou um link simbólico, use este:
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
Explicação: O comando "ls" fornece um erro "ls: / x: Esse arquivo ou diretório não existe" se o diretório ou o link simbólico não existir e também define o código de retorno, que você pode recuperar via "$?", Para não nulo (normalmente "1"). Certifique-se de verificar o código de retorno diretamente após chamar "ls".
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(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 um problema for encontrado com uma das abordagens fornecidas acima:
Com o ls
comando; os casos em que um diretório não existe - uma mensagem de erro é mostrada
[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists
-ksh: not: not found [Esse arquivo ou diretório não existe]
Existem ótimas soluções por aí, mas, em última análise, todo script falhará se você não estiver no diretório certo. Então, codifique assim:
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
será executado com êxito somente se, no momento da execução, você estiver em um diretório com um subdiretório que você verificará.
Entendo a pergunta inicial como esta: verificar se existe um diretório, independentemente da posição do usuário no sistema de arquivos. Portanto, usar 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 curingas, um recurso útil na busca de arquivos / diretórios. O único problema é que, se o diretório pesquisado não existir, o comando 'find' não imprimirá nada na saída padrão (não é uma solução elegante para o meu gosto) e terá, no entanto, uma saída zero. Talvez alguém possa melhorar isso.
locate
, mas não bom para qualquer outra coisa ...
--
é altamente recomendado (marcador de fim de opções). Caso contrário, se sua variável contiver algo que se parece com uma opção, o script falhará como nos espaços.