Comment vérifier si un lien symbolique existe

208

J'essaie de vérifier si un lien symbolique existe dans bash. Voici ce que j'ai essayé.

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

Cependant, cela ne fonctionne pas. Si '!' est omis, il ne se déclenche jamais. Et si '!' est là, il se déclenche à chaque fois.

ours
la source
2
pour ce que ça vaut, si vous utilisez [[! -D $ mda]] fonctionne très bien ..
DMin

Réponses:

328

-Lrenvoie true si le "fichier" existe et est un lien symbolique (le fichier lié peut exister ou non). Vous voulez -f(renvoie vrai si le fichier existe et est un fichier normal) ou peut-être juste -e(retourne vrai si le fichier existe quel que soit le type).

Selon la page de manuel GNU , -hest identique à -L, mais selon la page de manuel BSD , il ne devrait pas être utilisé:

-h file Vrai si le fichier existe et est un lien symbolique. Cet opérateur est conservé pour des raisons de compatibilité avec les versions précédentes de ce programme. Ne comptez pas sur son existence; utilisez plutôt -L.

drysdam
la source
2
Je cherche à voir si un lien symbolique N'EXISTE PAS. ! -h ou! -L devrait fonctionner pour les liens symboliques,! -e devrait fonctionner autrement.
porter le
48
Pour aider quiconque trouve cela via Google comme moi, la syntaxe complète à l'aide !est de if ! [ -L $mda ]; then .... fi mettre le point d'exclamation en dehors des crochets.
Sam
19
Je voulais juste ajouter un petit quelque chose au conseil donné par @Sam; lorsque vous effectuez ce type d'opérations, assurez-vous de mettre votre nom de fichier entre guillemets, pour éviter les problèmes avec les espaces. par exemple if [ ! -L "$mda" ]; then ... fi(note: if [ ! ... ]et if ! [ ... ]sont identiques :)
Thomas Vervest
2
voyez-vous vraiment une différence entre -L et -h? dans mon bash (version 4.2.53 (1) -release (x86_64-redhat-linux-gnu) man bash est identique pour -L et -h et ils se comportent de la même manière, c'est-à-dire qu'ils vérifient que le fichier est bien un lien peu
importe
3
Oui, -Let ce -hsont les mêmes . man testle confirme également.
Sparhawk
39

-L est le test pour le fichier existe et est également un lien symbolique

Si vous ne voulez pas tester si le fichier est un lien symbolique, mais juste tester pour voir s'il existe quel que soit le type (fichier, répertoire, socket, etc.), utilisez -e

Donc, si le fichier est vraiment un fichier et pas seulement un lien symbolique, vous pouvez faire tous ces tests et obtenir un état de sortie dont la valeur indique la condition d'erreur.

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
la source
16
-e "${file}"échoue si le lien symbolique existe mais que sa cible n'existe pas.
Flimm
1
Même résultat que Flimm. Je suis sous OS X. Pour moi, -L et -h fonctionnent pour les liens symboliques, mais pas -e ou -f.
pauljm
2
@Flimm, donc si je veux juste tester si un nom de fichier est pris (que ce soit un fichier ou un lien symbolique sans cible existante), quelle est la meilleure façon de le faire? apparemment -e ne fonctionne pas
dragonxlwang
38

Vous pouvez vérifier l'existence d'un lien symbolique et qu'il n'est pas rompu avec:

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

Ainsi, la solution complète est:

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
la source
2
-L teste s'il y a un lien symbolique, cassé ou non. En combinant avec -e, il est possible de tester si le lien est également valide (lien vers un répertoire ou un fichier). Votant pour ces solutions, car je trouve important de saisir cet aspect.
Torbjörn Österdahl
14

C'est peut-être ce que vous recherchez. Pour vérifier si un fichier existe et n'est pas un lien.

Essayez cette commande:

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

Que diriez-vous d'utiliser 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
la source
4

Le fichier est-il vraiment un lien symbolique? Sinon, le test habituel d'existence est -rou -e.

Tu vois man test.

DigitalRoss
la source
3

Si vous testez l'existence d'un fichier, vous ne voulez -e pas -L. -L teste un lien symbolique.

Andrew Lazarus
la source
Je cherche à voir si un lien symbolique N'EXISTE PAS. ! -h ou! -L devrait fonctionner pour les liens symboliques,! -e devrait fonctionner autrement.
porter le
3
Ce que vous voulez n'est pas clair. Le fichier existe et n'est pas un lien symbolique? Ensuite , testez les deux -e et! -H.
Andrew Lazarus
3
  1. vous pouvez d'abord faire avec ce style:

    mda="/usr/mda"
    if [ ! -L "${mda}" ]; then
      echo "=> File doesn't exist"
    fi
  2. si vous voulez le faire dans un style plus avancé, vous pouvez l'écrire comme ci-dessous:

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

le résultat ci-dessus est comme:

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
la source
La première invocation est incorrecte si le fichier existe mais n'est pas un lien ou est un lien pendant. La seconde est fausse si le chemin est un lien symbolique pendant.
Jonathan Tomer