2009-07-14 11 views
3

Quelle serait une manière élégante de comparer 2 liens symboliques sous Unix?Comment comparer 2 liens symboliques sous unix (Linux)?

On suppose que je suis entré dans les commandes suivantes:

ln -s /usr/share/g s1 
ln -s /usr/share/g s2 
ln -s ../share/g /usr/lib/s3 
ln -s /usr/share/h s4 

alors je voudrais avoir une commande qui dit que s1 et s2 sont égaux (si/usr/share/g existe réellement est pas pertinent), que s1 et s4 ne sont pas égaux, s2 et s4 ne sont pas égaux. (Pour mon but, il suffit que s3 soit différent de s1 et s2, mais si une comparaison après la normalisation de chemin peut être faite, cela peut être utile.)

Répondre

12

Pour les systèmes GNU (et peut-être d'autres, mais je ne peux pas dire), il y a readlink(1) :

$ touch a 
$ ln -s a b 
$ readlink b 
a 

Vous pouvez l'utiliser dans les comparaisons:

$ test $(readlink -f a) = $(readlink -f b) 
$ echo $? 
0 
+1

+1 Ooh, je ne connaissais pas celui-là! – DrAl

+0

Merci! C'est ce que je cherchais. –

+0

L'utilitaire stat (readlink) est apparu dans NetBSD 1.6. –

3

Vous pouvez faire un stat -L sur le fichier et comparer numéro de périphérique et d'inode. exemple rapide:

#!/bin/bash 
DI_A=$(stat -c "%d.%i" -L "$1") 
DI_B=$(stat -c "%d.%i" -L "$2") 

if [ "$DI_A" == "$DI_B" ]; then 
    echo "same file" 
else 
    echo "other file" 
fi 
+1

Il ne semble pas fonctionner sur les liens pendants. –

0

Soit utiliser stat -L ou analyser la sortie de ls -l (avec sed ou coupé ou similaire):

fileone=`ls -l s1 | sed 's/.*-> //'` 
filetwo=`ls -l s2 | sed 's/.*-> //'` 
if [ "$fileone" = "$filetwo" ] 
then 
    echo "They're the same!" 
fi 

Pour normalisent le chemin, utilisez realpath:

fileone=`ls -1 s1 | sed 's/.*-> //'` 
fileone=`realpath $fileone` 
# etc... 
+0

pauses sur les noms de fichiers contenant "->" ... merci pour le conseil realpath si. –

+0

Vrai ... je ne peux pas dire que j'ai jamais eu de fichiers avec -> en eux. Readlink est certainement le chemin à parcourir. – DrAl

-1

2 façons que je peux penser, vous pouvez utiliser ls -l sur les deux fichiers. vous pouvez voir après le « -> » de la sortie de la path.eg réelle

# ls -ltr msdfasdffff 
lrwxrwxrwx 1 root root 10 Jun 30 19:05 msdfasdffff -> blah.sh 

vous pouvez obtenir le nom de fichier en utilisant

# ls -l msdfasdffff | awk -F"-> " '{print $NF}' 
blah.sh 

alors vous pouvez comparer avec un autre lien.

l'autre est l'utilisation trouver

# var1=$(find . -name "s1" -printf "%l") 
# var2=$(find . -name "s2" -printf "%l") 

vous pouvez comparer les 2 variables utilisant if/else

+0

thx, mais la méthode awk casse sur les noms de fichiers contenant "->" comme sous-chaîne; la méthode find fonctionne, mais il manque quelques conditions pour restreindre la recherche à un seul fichier; Je préférerais la commande readlink alors. –

Questions connexes