Comment puis-je éditer des liens symboliques?

64

Ma compréhension de base d'un lien symbolique est un fichier spécial, un fichier contenant un chemin de chaîne vers un autre fichier. VFS du noyau fait abstraction de cela, mais y a-t-il une raison pour laquelle les liens symboliques semblent impossibles à modifier?

En d'autres termes: Puis-je éditer un lien symbolique? Si non pourquoi pas


Je comprends qu’il existe différentes manières de remplacer les liens symboliques (deux variantes se trouvent actuellement dans la section des réponses), mais il serait intéressant de savoir pourquoi le remplacement semble être le seul moyen de traiter les liens symboliques. Pourquoi ne pouvez-vous pas simplement changer où ils pointent?

Oli
la source
Votre compréhension est un peu limitée. la seule raison pour laquelle on l'appelle un «fichier» est qu'il n'y a pas de meilleur mot pour cela.
Shadur
5
Contrairement à l'atrocité embarrassante qu'est la variante Windows, les liens symboliques de style posix agissent sur / dans la couche de système de fichiers elle-même. La seule façon d'en éditer un serait d'éditer directement le système de fichiers - et généralement, cela ne vaut pas la peine.
Shadur
Les fichiers @Shadur .lnk ne sont pas vraiment des liens symboliques pour commencer (et NTFS possède des liens symboliques appropriés depuis Vista); ce sont plutôt des raccourcis pour exécuter des commandes, qu’il s’agisse de passer à un dossier spécifique ou de démarrer un programme avec des arguments spécifiques et avec un certain CWD.
JAB

Réponses:

36

Etant donné qu’un -fremplacement silencieux est possible, vous pouvez effectuer 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.

Oli
la source
7
Cela vous donne le remplacement atomique, bien que vous fassiez toujours un remplacement plutôt que d’éditer (le nouveau lien a un nouveau numéro d’inode).
Psusi
2
@ psusi Je suis tout à fait d'accord, c'est simplement une option techniquement légèrement meilleure que l'autre réponse dans certains scénarios.
Oli
Si vous redirigez le lien vers une autre destination, changer son numéro d'inode semble être un petit changement.
ams
4
Cela suppose linknamen'est pas un lien symbolique vers un répertoire. Utilisez l' -Toption sur mvsi vous êtes sur GNU ou -hsur FreeBSD pour éviter cela. Notez que ln -sfcela ne conserve pas les autorisations du lien (sur les systèmes où elles sont importantes).
Stéphane Chazelas
Une autre solution pour le changement symlink pour le répertoire est d'utiliser des -noptions , par exemple: ln -sfn DESTINATION_DIRECTORY LINK_NAME. En savoir plus sur askubuntu.com/a/186227/69004
sobi3ch
22

Si par édition, 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 -fparamètre ( --force), lorsqu'il est passé à ln, provoque l'appel de l' unlink()appel système juste avantsymlink()

Tiré de la réponse de débordement de pile suivante .

NlightNFotis
la source
9
Je pense qu'il est discutable de savoir si cela peut être considéré comme un "montage", puisque unlink (); symlink (); n’est pas atomique, il existe donc une infime période de temps pendant laquelle le lien n’existe pas.
rejouer
@ mauro.stettler Oui, vous avez raison. Mais je suppose que cela dépend de votre point de vue. Si vous ne tenez compte que du résultat final, vous pourrez peut-être le considérer comme modifié, sans autre considération.
NlightNFotis
1
La section citée du document Système de partage de temps Unix décrit les liens physiques. Ceux-ci sont entièrement différents des liens symboliques (liens symboliques) sur lesquels le PO s'est interrogé.
Ansgar Esztermann
4
Notez qu'il suppose que testla cible n'est pas un répertoire. Sinon ln -s -f .profile test, créerait un .profilelien symbolique dans ce répertoire. GNU lna une -Toption pour éviter cela.
Stéphane Chazelas
9

Les liens symboliques doivent être modifiés de manière atomique. Si vous les écrivez à mi-chemin, ils ne fonctionneront pas. Le contenu d'un lien symbolique est assez petit (au plus 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' symlinkappel système (plus l'interface générique unlinkpour supprimer tout fichier).

L' symlinkappel système crée uniquement un nouveau lien symbolique, il ne supprime aucun fichier existant. Ceci est gênant, mais cohérent avec les 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 ne pas remplacer un fichier existant par un fichier nouvellement créé) et mkdir.

Comme vous l'avez découvert dans le shell, vous ne pouvez pas remplacer un lien symbolique de manière atomique par la lncommande ( ln -sfdissociez le fichier précédent puis créez le lien symbolique), vous pouvez le faire en créant d'abord un lien symbolique sous un nom temporaire, puis puis le mettre en place.

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
Gilles, arrête de faire le mal
la source
2
mv -f(comme ln -sf) ne fera pas ce que vous voulez si $linkpointe vers un répertoire. GNU ln et mv en ont un -Tpour ça. mv(renommer l'appel système) changera toujours l'inode de $linktandis que ln -sfT(unlink + symlink) pourrait réutiliser le même.
Stéphane Chazelas
0

Techniquement, il n'y a pas de commande intégrée pour éditer un lien symbolique existant. Il peut être facilement réalisé avec quelques commandes courtes.

Voici une petite fonction bash / zsh que j'ai écrite 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"
}
blizzrdof77
la source
Désolé, mais votre "réponse" est uniquement liée à distance à la question posée.
user2233709
Bonjour @ utilisateur2233709 - la question de l'utilisateur " Comment puis-je modifier des liens symboliques? " A été clairement répondue dans la première phrase, ainsi qu'en apportant une solution. Pourriez-vous élaborer?
blizzrdof77
2
Avez-vous vraiment lu la question? Il s'agit de savoir s'il est possible de modifier un lien symbolique plutôt que de le remplacer . Votre «solution» proposée est un script qui remplace un lien symbolique.
user2233709
0

Supposons que linkname existe après avoir effectué (par le passé):

 ln -s   /the/path/to/a/file   linkname

Ensuite, il y a trois façons de changer le lien symbolique:

  • Utilisez ln avec -fforce et même pour les répertoires -n(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 mvil (changement atomique même pour les répertoires):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
Isaac
la source