Verifique se o diretório existe usando o caractere inicial (~) no bash falha


16

Por que o seguinte bashverifica se um diretório falha?

if [ ! -d "~/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

~/Desktopde fato existe. Este é um Mac por sinal.


O problema é com esse tipo de script

read -p "Provide the destination directory: " DESTINATION

if [ ! -d $DESTINATION ]; then
    echo "\t'$DESTINATION' does not exist." >&2;
    exit 1;
fi

1
Assim como quando cd "~/Desktop"você também recebe um erro. Ele deve ser não citado ou armazenado como uma variável (sem aspas). Por exemplo, a=~/Desktop; cd $a;funciona, mas não a="~/Desktop"; cd Desktop;Veja serverfault.com/questions/417252/...
dylnmc

Respostas:


7

Justin esclareceu sua pergunta em seu primeiro comentário sobre a resposta dos quanta. Ele está lendo uma linha de texto usando read(ou por outros meios dinâmicos) e deseja expandir o til.

A pergunta se torna "Como você realiza a expansão de til no conteúdo de uma variável?"

A abordagem geral é usar eval, mas vem com algumas advertências importantes, como espaços e redirecionamento de saída ( >) na variável. O seguinte parece funcionar para mim:

read -p "Provide the destination directory: " DESTINATION

if [ ! -d "`eval echo ${DESTINATION//>}`" ]; then
    echo "'$DESTINATION' does not exist." >&2;
    exit 1;
fi

Experimente com cada uma das seguintes entradas:

~
~/existing_dir
~/existing dir with spaces
~/nonexistant_dir
~/nonexistant dir with spaces
~/string containing > redirection
~/string containing > redirection > again and >> again

Explicação

  • O ${mypath//>}retira >personagens que poderia espancar um arquivo durante a eval.
  • O eval echo ...que é a expansão de til atual
  • As aspas duplas ao redor do evalsão para suporte de nomes de arquivos com espaços.

Como complemento, você pode melhorar o UX adicionando a -eopção de ler:

read -p "Provide the destination directory: " -e DESTINATION

Agora, quando o usuário digitar til e clicar na guia, ele será expandido. Essa abordagem não substitui a abordagem de avaliação acima, no entanto, como a expansão só acontece se o usuário clicar na guia. Se ele digitar ~ / foo e pressionar enter, ele permanecerá como um til.

Veja também:


23

Remova as aspas duplas ao redor do diretório para ver se funciona:

if [ ! -d ~/Desktop ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

A razão para isso é que a expansão til só funciona quando não está entre aspas.

info "(bash) Tilde Expansion"

3.5.2 Tilde Expansion
---------------------

If a word begins with an unquoted tilde character (`~'), all of the
characters up to the first unquoted slash (or all characters, if there
is no unquoted slash) are considered a TILDE-PREFIX.  If none of the
characters in the tilde-prefix are quoted, the characters in the
tilde-prefix following the tilde are treated as a possible LOGIN NAME.
If this login name is the null string, the tilde is replaced with the
value of the `HOME' shell variable.  If `HOME' is unset, the home
directory of the user executing the shell is substituted instead.
Otherwise, the tilde-prefix is replaced with the home directory
associated with the specified login name.

Que tal se o valor chegar dinamicamente. Ou seja ( pastie.org/4471350 ) e DESTINATIONé ~/Desktop.
23412 Justin

3
A expansão de til é feita quando a variável é definida, não quando é avaliada; portanto, esse não é um exemplo justo.
MadHatter

+1, isso é suficiente para resolver o meu problema.
Flying Fisher


1

corre

echo $HOME

use $HOMEe verifique se o usuário está realmente usando o script. se o root usa ~sua busca /root, não /home/$USER.

if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

-1
if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

deve ser $ HOME em vez de ~

~ é uma coisa do TECLADO


Se você ler a outra resposta aqui, perceberá que isso está errado.
pintainhos
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.