Qual comando pode ser usado para verificar se um diretório existe ou não, dentro de um script de shell Bash?
3725
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á.
--
é 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.[ ! -d "$DIRECTORY" ]
será verdade tanto se$DIRECTORY
não existe, ou se faz existir, mas não é um diretório. Considere algo comoif [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; isso falhará se"$DIRECTORY"
for um arquivo. (Claro que você deve verificar semkdir
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, comoif [ -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.fonte
Observe que o teste -d pode produzir alguns resultados surpreendentes:
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:
Você pode encontrar mais informações no manual do Bash sobre expressões condicionais do Bash e o
[
comando builtin e o comando[[
composto .fonte
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 duplo
test
torna os testes lógicos de escrita mais naturais:fonte
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:
fonte
if $dir is a dir, then echo "yes"
:? Um pouco de explicação ajudaria :)cmd && other
é uma abreviação comum paraif 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 acreditoset -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:Você também pode fazer isso de forma negativa:
Nota : tenha cuidado. Deixe espaços vazios em ambos os lados das chaves de abertura e fechamento.
Com a mesma sintaxe, você pode usar:
fonte
Um script simples para testar se um diretório ou arquivo está presente ou não:
Um script simples para verificar se o diretório está presente ou não:
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 quetempdir
já esteja presente. Em seguida,mkdir tempdir
ocorrerá um erro como abaixo:fonte
Você pode usar
test -d
(verman test
).Por exemplo:
Nota: O
test
comando é o mesmo que a expressão condicional[
(consulteman [
:), portanto, é portátil nos scripts de shell.Para opções possíveis ou ajuda adicional, verifique:
help [
help test
man test
ouman [
fonte
Ou para algo completamente inútil:
fonte
Aqui está um idioma muito pragmático:
Normalmente, envolvo-o em uma função:
Ou:
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 executarcd
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:e
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ãodirectory
. Nesse nível, prefiro mantê-lo simples - os argumentos para uma função são apenas strings.fonte
test -d
como o @Grundlefleck explicou.test -d /unreadable/exists
falhará, mesmo se o argumento existir.O código acima verifica se o diretório existe e se é gravável.
fonte
Experimente on-line
fonte
space
depois[
-> [ `` -d . Eu tenho erro por falta de espaçoDigite este código no prompt do Bash:
fonte
Mais recursos usando
find
Verifique a existência da pasta nos subdiretórios:
Verifique a existência de uma ou várias pastas com base em um padrão no diretório atual:
Ambas as combinações. No exemplo a seguir, ele verifica a existência da pasta no diretório atual:
fonte
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:
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.fonte
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:
Se o caminho que você der
pushd
existir, você o entrará e sairá com0
, o que significa que athen
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:
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 seuthen
bloco será ignorado. Se você experimentá-los em arquivos que existem, o comando será executado e sairá com um status de0
, permitindo que seuthen
bloco seja executado.fonte
Explicação:
-d
: verifique se é um diretório-L
: verifique se é um link simbólicofonte
Para verificar mais de um diretório, use este código:
fonte
Verifique se o diretório existe, ou faça um:
fonte
mkdir -p "$DIRECTORY"
para o mesmo efeito.fonte
Esta resposta foi embrulhada como um script de shell
Exemplos
is_dir
fonte
O uso da
-e
verificação verificará arquivos e isso inclui diretórios.fonte
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:fonte
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:
fonte
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
fonte
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 umd
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:Uso prático:
fonte
fonte
Se você deseja verificar se existe um diretório, independentemente de ser um diretório real ou um link simbólico, use este:
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".
fonte
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(1)
2)
(3)
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 é mostradafonte
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:
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:
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.
fonte
locate
, mas não bom para qualquer outra coisa ...