Jak sprawdzić, czy istnieje dowiązanie symboliczne

208

Próbuję sprawdzić, czy dowiązanie symboliczne istnieje w bash. Oto, co próbowałem.

mda=/usr/mda
if [ ! -L $mda ]; then
  echo "=> File doesn't exist"
fi


mda='/usr/mda'
if [ ! -L $mda ]; then
  echo "=> File doesn't exist"
fi

To jednak nie działa. Jeśli '!' jest pominięty, nigdy się nie uruchamia. I jeśli '!' jest tam, uruchamia się za każdym razem.

Niedźwiedź
źródło
2
za jaką wartość, jeśli użyjesz [[! -D $ mda]] działa dobrze ..
DMin 13.12.17

Odpowiedzi:

327

-Lzwraca wartość true, jeśli „plik” istnieje i jest dowiązaniem symbolicznym (połączony plik może, ale nie musi istnieć). Chcesz -f(zwraca true, jeśli plik istnieje i jest zwykłym plikiem), a może po prostu -e(zwraca true, jeśli plik istnieje bez względu na typ).

Według podręcznika GNU , -hjest identyczny -L, ale według podręcznika BSD , nie należy stosować:

-h file Prawda, jeśli plik istnieje i jest dowiązaniem symbolicznym. Ten operator jest zachowany dla kompatybilności z poprzednimi wersjami tego programu. Nie polegaj na jego istnieniu; zamiast tego użyj -L.

drysdam
źródło
2
Szukam, czy dowiązanie symboliczne NIE istnieje. ! -h lub! -L powinien działać dla dowiązań symbolicznych,! -e powinien działać inaczej.
ponieść
48
Aby pomóc każdemu, kto znajdzie to za pośrednictwem Google tak jak ja, pełną składnią !jest if ! [ -L $mda ]; then .... fi np. Umieszczenie wykrzyknika poza nawiasami kwadratowymi.
Sam
19
Chciałem tylko dodać coś do końcówki podanej przez @Sam; wykonując tego rodzaju operacje, pamiętaj o umieszczeniu nazwy pliku w cudzysłowie, aby uniknąć problemów z białymi spacjami. np. if [ ! -L "$mda" ]; then ... fi(uwaga: if [ ! ... ]i if ! [ ... ]są identyczne :)
Thomas Vervest,
2
czy naprawdę widzisz różnicę między -L i -h? w moim bashu (wersja 4.2.53 (1) -release (x86_64-redhat-linux-gnu) man bash jest identyczny dla obu -L i -h i zachowują się tak samo, tzn. sprawdzają, czy plik faktycznie jest linkiem i nie nie ma znaczenia, czy link do pliku istnieje, czy nie.
philippe lhardy
3
Tak -Li -hsą takie same . man testrównież to potwierdza.
Sparhawk
39

-L oznacza, że ​​istnieje test dla pliku i jest on również dowiązaniem symbolicznym

Jeśli nie chcesz testować, czy plik jest dowiązaniem symbolicznym, ale po prostu sprawdź, czy istnieje niezależnie od typu (plik, katalog, gniazdo itp.), Użyj -e

Więc jeśli plik jest naprawdę plikiem, a nie tylko dowiązaniem symbolicznym, możesz wykonać wszystkie te testy i uzyskać status wyjścia, którego wartość wskazuje na błąd.

if [ ! \( -e "${file}" \) ]
then
     echo "%ERROR: file ${file} does not exist!" >&2
     exit 1
elif [ ! \( -f "${file}" \) ]
then
     echo "%ERROR: ${file} is not a file!" >&2
     exit 2
elif [ ! \( -r "${file}" \) ]
then
     echo "%ERROR: file ${file} is not readable!" >&2
     exit 3
elif [ ! \( -s "${file}" \) ]
then
     echo "%ERROR: file ${file} is empty!" >&2
     exit 4
fi
Corin
źródło
16
-e "${file}"kończy się niepowodzeniem, jeśli dowiązanie symboliczne istnieje, ale jego cel nie istnieje.
Flimm
1
Taki sam wynik jak Flimm. Jestem na OS X. Dla mnie -L i -h pracują dla dowiązań symbolicznych, ale nie -e lub -f.
pauljm
2
@Flimm, więc jeśli chcę tylko przetestować, czy nazwa pliku jest pobierana (czy to plik, czy dowiązanie symboliczne bez celu), jaki jest najlepszy sposób? najwyraźniej -e nie działa
dragonxlwang
38

Możesz sprawdzić istnienie dowiązania symbolicznego i czy nie jest zerwane z:

[ -L ${my_link} ] && [ -e ${my_link} ]

Kompletne rozwiązanie to:

if [ -L ${my_link} ] ; then
   if [ -e ${my_link} ] ; then
      echo "Good link"
   else
      echo "Broken link"
   fi
elif [ -e ${my_link} ] ; then
   echo "Not a link"
else
   echo "Missing"
fi
Chen Levy
źródło
2
-L test, czy dowiązanie symboliczne jest uszkodzone, czy nie. Łącząc z -e można sprawdzić, czy łącze jest również prawidłowe (połączenie z katalogiem lub plikiem). Głosowanie za tymi rozwiązaniami, ponieważ uważam, że ważne jest uchwycenie tego aspektu.
Torbjörn Österdahl
14

Może tego właśnie szukasz. Aby sprawdzić, czy plik istnieje i nie jest łączem.

Wypróbuj to polecenie:

file="/usr/mda" 
[ -f $file ] && [ ! -L $file ] && echo "$file exists and is not a symlink"
Zlinczować
źródło
8

Co powiesz na używanie readlink?

# if symlink, readlink returns not empty string (the symlink target)
# if string is not empty, test exits w/ 0 (normal)
#
# if non symlink, readlink returns empty string
# if string is empty, test exits w/ 1 (error)
simlink? () {
  test "$(readlink "${1}")";
}

FILE=/usr/mda

if simlink? "${FILE}"; then
  echo $FILE is a symlink
else
  echo $FILE is not a symlink
fi
popedotninja
źródło
4

Czy plik naprawdę jest dowiązaniem symbolicznym? Jeśli nie, zwykłym testem na istnienie jest -rlub -e.

Zobaczyć man test.

DigitalRoss
źródło
3

Jeśli testujesz istnienie pliku, chcesz, aby nie -e -L. -L testy dla dowiązania symbolicznego.

Andrew Lazarus
źródło
Szukam, czy dowiązanie symboliczne NIE istnieje. ! -h lub! -L powinien działać dla dowiązań symbolicznych,! -e powinien działać inaczej.
ponieść
3
To, czego chcesz, nie jest jasne. Plik istnieje i nie jest dowiązaniem symbolicznym? Następnie przetestuj zarówno -e, jak i! -H.
Andrew Lazarus,
3
  1. najpierw możesz zrobić z tym stylem:

    mda="/usr/mda"
    if [ ! -L "${mda}" ]; then
      echo "=> File doesn't exist"
    fi
  2. jeśli chcesz to zrobić w bardziej zaawansowanym stylu, możesz napisać to tak:

    #!/bin/bash
    mda="$1"
    if [ -e "$1" ]; then
        if [ ! -L "$1" ]
        then
            echo "you entry is not symlink"
        else
            echo "your entry is symlink"
        fi
    else
      echo "=> File doesn't exist"
    fi

wynik powyżej jest następujący:

root@linux:~# ./sym.sh /etc/passwd
you entry is not symlink
root@linux:~# ./sym.sh /usr/mda 
your entry is symlink
root@linux:~# ./sym.sh 
=> File doesn't exist
Amin Shateri
źródło
Pierwsze wywołanie jest nieprawidłowe, jeśli plik istnieje, ale nie jest łączem lub jest wiszącym łączem. Drugi jest błędny, jeśli ścieżka jest wiszącym dowiązaniem symbolicznym.
Jonathan Tomer,