Eu estava escrevendo alguns scripts e escrevi algo como
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
O que aconteceu é que, por estupidez, executei a segunda linha sem executar a primeira. Acontece que [-d ""] retorna verdadeiro e a expressão se torna
rm -rf /*
Felizmente, era apenas uma máquina de teste e eu não era um sudo, mas apesar de ter perdido alguns dados
Minha pergunta é: por que [-d ""] retorna true ?? a documentação afirma claramente que verifica se existe um caminho e se é uma pasta
Eu resolvi o problema usando
[ -e $ARTIFACTS ]
o que parece funcionar
Felicidades
rm -rf $ARTIFACTS
sem o/*
. Isso também excluiria o$ARTIFACTS
diretório, o que é bom, porque se eu quiser ter certeza de que ele existe antes de colocar algo nele, executarei demkdir -p $ARTIFACTS
qualquer maneira. Ele também excluirá os arquivos ocultos$ARTIFACTS
, o que também é bom, porque eu não escreveriarm -rf $ARTIFACTS/*
se$ARTIFACTS
contivesse algo que quisesse salvar.Respostas:
1. Esses dois testes retornam true :
de acordo com o POSIX (conforme explicado pelo @Tim).
2. Mas isso retorna falso ( não é verdade, como indicado na pergunta)
porque
test
é chamado com dois argumentos (embora o segundo seja uma sequência vazia).3. É por isso que é uma boa prática usar, em
[[ … ]]
vez detest
([ … ]
), que a maioria das conchas atuais (todas?) Fornece. Essa construção verifica se você fornece argumentos suficientes (caso contrário, gera um erro e aborta)ou simplesmente se comporta como se poderia esperar:
4. E, como apontado por @Gilles, ainda mais importante é a substituição de aspas duplas. Portanto,
-d "$SOME_UNSET_VAR"
expande-d ""
e retorna falso, mesmo comtest
(igual ao caso 2). Portanto, isso também é compatível com o shell Bournesh
:testado com o bash 3.00.16 (1) e 4.1.5 (1)
fonte
[[ … ]]
mas não são simplessh
. A prática realmente importante é colocar aspas em torno substituições de comando :[ -d "$ARTIFACTS" ]
.Esta pergunta já foi respondida no StackOverflow. Ele diz que, de acordo com o padrão POSIX,
test
sempre deve retornar bem-sucedido se for chamado com exatamente um argumento não vazio (e nenhum outro argumento).Esse também deve ser o caso
test -e
(e de fato está no meu sistema), portanto, tenha cuidado.Em vez disso, use:
test
será chamado com dois argumentos, mesmo que a variável esteja vazia e retorne false nesse caso.fonte
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
não é melhor: apenas atende ao caso específico quando$ARTIFACTS
está vazio, mas falha quando$ARTIFACTS
pode conter espaços em branco ou\[?*
.[ -d "$ARTIFACTS" ]
é a maneira correta de fazer isso (ou[[ -d $ARTIFACTS ]]
em conchas que possuem[[ … ]]
).Você está errado . Funciona porque
$ARTIFACTS
agora está definido como algo.Quando uma variável não está definida, então diz
ou
seria tanto avaliar a
true
porque implica dizere
respectivamente. (Dizendo
[ foobar ]
sempre avaliaria como verdadeiro.)Dizendo
é útil nessas situações.
help set
diria a você:fonte
Veja que você configurou a variável ARTIFACTS e estava verificando ARTIFCATS. Provavelmente digitando errado?
De qualquer forma, -d e -e produziriam os mesmos resultados em variáveis não definidas.
Portanto, use aspas duplas e ele irá ajudá-lo.
NOTA: Se o seu "/ SOME / PATH" tiver alguma pasta com espaço, o script que você mencionou será interrompido com o erro "esperado pelo operador binário".
Exemplo:
vai dar certo. Não se esqueça de colocar aspas na
rm
invocação também (rm -rf $ARTIFACTS
removeria com alegria/home
e reclamaria porbackup/*
não existir).Além disso, incluir
-L
check garantirá que seja um diretório e não apenas um link simbólico para um diretório.Então, basicamente,
fonte