Ma compréhension de base d'un lien symbolique est comme un fichier spécial, un fichier qui contient un chemin de chaîne vers un autre fichier. Le VFS du noyau en résume beaucoup, mais y a-t-il une raison pour laquelle les liens symboliques semblent impossibles à modifier?
En d'autres termes: puis-je modifier un lien symbolique? Sinon, pourquoi pas?
Je comprends qu'il existe différentes façons de remplacer les liens symboliques (deux alternatives sont actuellement dans la section des réponses) mais il serait intéressant d'obtenir une explication sur la raison pour laquelle le remplacement semble être le seul moyen de traiter les liens symboliques . Pourquoi ne pouvez-vous pas simplement changer de point
Étant donné que -f
fait juste un remplacement silencieux, vous pouvez faire un remplacement atomique avec mv -T
(-T le fait fonctionner même si /loc.../link est un répertoire) :
ln -s /location/to/link linkname
# ...
ln -s /location/to/link2 newlink
mv -T newlink linkname
linkname
est accessible tout au long du processus.
Si par modification, vous voulez changer le fichier vers lequel il pointe, alors oui vous pouvez:
$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 Pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 Pascal pascal 8 2009-09-23 17:12 test -> .profile
Le paramètre -f
(--force
) Lorsqu'il est passé à ln, il appelle l'appel système unlink()
juste avant symlink()
Tiré de ce qui suit réponse de débordement de pile .
Les liens symboliques doivent être modifiés atomiquement. Si vous êtes à mi-chemin de les écrire, ils ne fonctionneront pas. Le contenu d'un lien symbolique est assez petit (au maximum 4095 caractères sous Linux: la longueur maximale d'un chemin d'accès à un fichier), il serait donc inutile de modifier une partie d'un lien symbolique au niveau du noyau. Par conséquent, le noyau n'offre aucune interface pour éditer un lien symbolique, seulement une interface pour en créer un nouveau, l'appel système symlink
(plus l'interface générique unlink
pour supprimer n'importe quel fichier).
L'appel système symlink
crée uniquement un nouveau lien symbolique, il ne supprime aucun fichier existant. C'est ennuyeux, mais cohérent avec d'autres appels système pour créer des fichiers tels que open
(qui peut créer un nouveau fichier ou tronquer un fichier existant, mais pas remplacer un fichier existant par un fichier nouvellement créé) et mkdir
.
Dans le Shell, comme vous avez découvert , alors que vous ne pouvez pas remplacer un lien symbolique de manière atomique par la commande ln
(ln -sf
dissocie le fichier précédent puis crée le lien symbolique), vous pouvez le faire en créant d'abord un lien symbolique sous un nom temporaire puis en le déplaçant en place.
tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
Techniquement, il n'y a pas de commande intégrée pour modifier un lien symbolique existant. Il peut être facilement réalisé avec quelques commandes courtes.
Voici un peu fonction bash/zsh J'ai écrit pour mettre à jour un lien symbolique existant:
# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with
# -----------------------------------------
function edit-symlink () {
if [ -z "$1" ]; then
echo "Name of symbolic link you would like to edit:"
read LINK
else
LINK="$1"
fi
LINKTMP="$LINK-tmp"
if [ -z "$2" ]; then
echo "Full destination path to update existing symlink with:"
read DEST
else
DEST="$2"
fi
ln -s $DEST $LINKTMP
rm $LINK
mv $LINKTMP $LINK
printf "Updated $LINK to point to new destination -> $DEST"
}
Supposons que le nom du lien existe à la suite d'avoir fait (dans le passé):
ln -s /the/path/to/a/file linkname
Ensuite, il existe trois façons de modifier le lien symbolique:
Utilisez ln avec -f
forcer et même pour les répertoires -n
(l'inode pourrait être réutilisé):
ln -sfn /some/new/path linkname
Supprimez le lien symbolique et créez-en un nouveau (même pour les répertoires):
rm linkname; ln -s /some/new/path linkname
créer un nouveau lien symbolique, puis mv
it (changement atomique même pour les répertoires):
ln -s /some/new/path newlinkname
mv -fT newlinkname linkname # linkname remains after the command