Cómo verificar si existe un enlace simbólico

208

Estoy tratando de verificar si existe un enlace simbólico en bash. Esto es lo que he intentado.

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

Sin embargo, eso no funciona. Si '!' se deja afuera, nunca se dispara. Y si '!' está ahí, se dispara cada vez.

oso
fuente
2
por lo que vale, si usa [[! -D $ mda]] funciona bien ..
DMin

Respuestas:

328

-Ldevuelve verdadero si el "archivo" existe y es un enlace simbólico (el archivo vinculado puede o no existir). Desea -f(devuelve verdadero si el archivo existe y es un archivo normal) o tal vez solo -e(devuelve verdadero si el archivo existe independientemente del tipo).

De acuerdo con la página de manual de GNU , -hes idéntico a -L, pero de acuerdo con la página de manual de BSD , no debe usarse:

-h file Verdadero si el archivo existe y es un enlace simbólico. Este operador se mantiene por compatibilidad con versiones anteriores de este programa. No confíes en su existencia; use -L en su lugar.

Drysdam
fuente
2
Estoy buscando para ver si NO existe un enlace simbólico. ! -h o! -L debería funcionar para enlaces simbólicos,! -e debería funcionar de otra manera.
oso
48
Para cualquier ayuda que encuentra presente a través de Google como lo hice, la sintaxis completa usando !es if ! [ -L $mda ]; then .... fi decir, poner el signo de exclamación fuera de los corchetes.
Sam
19
Solo quería agregar algo al consejo dado por @Sam; al hacer este tipo de operaciones, asegúrese de poner su nombre de archivo entre comillas, para evitar problemas con los espacios en blanco. por ejemplo if [ ! -L "$mda" ]; then ... fi(nota: if [ ! ... ]y if ! [ ... ]son idénticos :)
Thomas Vervest
2
¿realmente ves una diferencia entre -L y -h? en mi bash (versión 4.2.53 (1) -release (x86_64-redhat-linux-gnu) man bash es idéntico tanto para -L como para -h y se comportan igual, es decir, comprueban que el archivo es realmente un enlace y no 'no importa si el
enlace
3
Sí, -Ly -hson lo mismo . man testTambién confirma esto.
Sparhawk
39

-L es la prueba de archivo existente y también es un enlace simbólico

Si no desea probar que el archivo sea un enlace simbólico, solo pruebe para ver si existe independientemente del tipo (archivo, directorio, socket, etc.) y luego use -e

Entonces, si el archivo es realmente un archivo y no solo un enlace simbólico, puede hacer todas estas pruebas y obtener un estado de salida cuyo valor indica la condición de error.

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
fuente
16
-e "${file}"falla si el enlace simbólico existe pero su objetivo no existe.
Flimm
1
Mismo resultado que Flimm. Estoy en OS X. Para mí, -L y -h funcionan para enlaces simbólicos, pero no -e o -f.
pauljm
2
@Flimm, así que si solo quiero probar si se toma un nombre de archivo (ya sea un archivo o un enlace simbólico sin destino), ¿cuál es la mejor manera de hacerlo? aparentemente, no funciona
dragonxlwang
38

Puede verificar la existencia de un enlace simbólico y que no está roto con:

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

Entonces, la solución completa es:

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
fuente
2
-L prueba si hay un enlace simbólico, roto o no. Al combinar con -e es posible probar si el enlace también es válido (enlazando a un directorio o archivo). Votar estas soluciones, ya que me parece importante capturar este aspecto.
Torbjörn Österdahl
14

Quizás esto es lo que estás buscando. Para verificar si existe un archivo y no es un enlace.

Prueba este comando:

file="/usr/mda" 
[ -f $file ] && [ ! -L $file ] && echo "$file exists and is not a symlink"
Linchar
fuente
8

¿Qué tal el uso 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
fuente
4

¿Es el archivo realmente un enlace simbólico? Si no, la prueba habitual de existencia es-r o-e .

Ver man test.

DigitalRoss
fuente
3

Si está probando la existencia de un archivo, quiere -e no -L. -L prueba para un enlace simbólico.

Andrew Lazarus
fuente
Estoy buscando para ver si NO existe un enlace simbólico. ! -h o! -L debería funcionar para enlaces simbólicos,! -e debería funcionar de otra manera.
oso
3
Lo que quieres no está claro. El archivo existe y no es un enlace simbólico? Luego pruebe ambos -e y! -H.
Andrew Lazarus el
3
  1. primero puedes hacer con este estilo:

    mda="/usr/mda"
    if [ ! -L "${mda}" ]; then
      echo "=> File doesn't exist"
    fi
  2. si quieres hacerlo en un estilo más avanzado puedes escribirlo como a continuación:

    #!/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

El resultado de arriba es como:

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
fuente
La primera invocación es incorrecta si el archivo existe pero no es un enlace o es un enlace colgante. El segundo es incorrecto si la ruta es un enlace simbólico colgante.
Jonathan Tomer el