Sprawdź, czy katalog istnieje przy użyciu znaku domowego (~) w bash kończy się niepowodzeniem

16

Dlaczego poniższe elementy bashsprawdzają, czy katalog nie działa?

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

~/Desktopnaprawdę istnieje. Nawiasem mówiąc, jest to na komputerze Mac.


Problem dotyczy tego typu skryptu

read -p "Provide the destination directory: " DESTINATION

if [ ! -d $DESTINATION ]; then
    echo "\t'$DESTINATION' does not exist." >&2;
    exit 1;
fi
Justin
źródło
1
Podobnie jak wtedy, gdy pojawia cd "~/Desktop"się błąd. Należy go cytować lub zapisać jako zmienną (bez cudzysłowów). Na przykład a=~/Desktop; cd $a;działa, ale nie a="~/Desktop"; cd Desktop;Zobacz Zobacz serverfault.com/questions/417252
dylnmc

Odpowiedzi:

7

Justin wyjaśnił swoje pytanie w swoim pierwszym komentarzu do odpowiedzi kwanty. Czyta wierszem tekstu read(lub innymi dynamicznymi środkami) i chce rozwinąć tyldę.

Pytanie brzmi: „W jaki sposób przeprowadzasz interpretację tyldy na zawartości zmiennej?”

Ogólne podejście polega na użyciu eval, ale wiąże się z pewnymi ważnymi zastrzeżeniami, mianowicie spacjami i przekierowaniem wyjścia ( >) w zmiennej. Wydaje mi się, że następujące działania:

read -p "Provide the destination directory: " DESTINATION

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

Wypróbuj z każdym z następujących danych wejściowych:

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

Wyjaśnienie

  • ${mypath//>}Wycina >znaków, które mogłyby sprać plik czasie eval.
  • To, eval echo ...co robi rzeczywiste rozszerzenie tyldy
  • Podwójne cudzysłowy wokół evalsłużą do obsługi nazw plików ze spacjami.

Jako uzupełnienie tego możesz ulepszyć UX, dodając -eopcję czytania:

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

Teraz, gdy użytkownik wpisze kartę tyldy i trafień, zostanie rozwinięta. Podejście to nie zastępuje jednak powyższego podejścia ewaluacyjnego, ponieważ rozwinięcie następuje tylko wtedy, gdy użytkownik kliknie kartę. Jeśli po prostu wpisze ~ / foo i uderzy enter, pozostanie to jak tylda.

Zobacz też:

Mag Noach
źródło
23

Usuń podwójne cudzysłowy wokół katalogu, aby zobaczyć, czy to działa:

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

Powodem tego jest, że rozszerzenie tyldy działa tylko wtedy, gdy nie jest cytowane.

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.
kwanty
źródło
A może wartość przyjdzie dynamicznie. Tj. ( Pastie.org/4471350 ) i DESTINATIONjest ~/Desktop.
Justin
3
Rozwinięcie tyldy odbywa się, gdy zmienna jest ustawiona, a nie podczas oceny, więc nie jest to dobry przykład.
MadHatter
+1, to wystarczy, aby rozwiązać mój problem.
Flying Fisher
1

biegać

echo $HOME

użyj $HOMEi upewnij się, że użytkownik faktycznie używa skryptu. jeśli root użyje ~go /root, to nie /home/$USER.

if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi
trzy szóstki
źródło
-1
if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

powinno być $ HOME zamiast ~

~ jest KLAWIATURĄ

LeoChu
źródło
Jeśli przeczytasz inną odpowiedź tutaj, zdasz sobie sprawę, że to źle.
pisklęta