Wie kann ich Symlinks bearbeiten?

64

Ich verstehe einen Symlink grundsätzlich als eine spezielle Datei, eine Datei, die einen Zeichenkettenpfad zu einer anderen Datei enthält. Das VFS des Kernels abstrahiert einen Großteil davon, aber gibt es einen Grund, warum Symlinks scheinbar nicht bearbeitet werden können?

Mit anderen Worten: Kann ich einen Symlink bearbeiten? Wenn nein, warum nicht?


Ich verstehe, dass es verschiedene Möglichkeiten gibt , Symlinks zu ersetzen (zwei Alternativen finden Sie derzeit im Abschnitt Antworten), aber es wäre interessant, eine Erklärung zu erhalten, warum das Ersetzen die einzige Möglichkeit zu sein scheint, mit Symlinks umzugehen. Warum kannst du nicht einfach ändern, wohin sie zeigen?

Oli
quelle
Ihr Verständnis ist etwas eingeschränkt; Der einzige Grund, warum es eine "Datei" genannt wird, ist, dass es kein besseres Wort dafür gibt.
Shadur
5
Anders als bei der peinlichen Gräueltat der Windows-Variante werden symbolische Verknüpfungen im Posix-Stil auf / in der Dateisystemebene selbst ausgeführt. Die einzige Möglichkeit zum Bearbeiten besteht darin, das Dateisystem direkt zu bearbeiten - und es lohnt sich im Allgemeinen nicht.
Shadur
@Shadur .lnk-Dateien sind anfangs keine echten Symlinks (und NTFS hat seit Vista die richtigen Symlinks). Sie sind eher Abkürzungen für die Ausführung von Befehlen, egal ob diese in einen bestimmten Ordner wechseln oder ein Programm mit bestimmten Argumenten und einer bestimmten CWD starten.
JAB

Antworten:

36

Da dies -fnur eine stille Ersetzung ist, können Sie eine atomare Ersetzung mit mv -T(-T bewirkt, dass es funktioniert, auch wenn /loc.../link ein Verzeichnis ist) :

ln -s /location/to/link linkname
# ... 
ln -s /location/to/link2 newlink
mv -T newlink linkname

linkname ist während des gesamten Prozesses zugänglich.

Oli
quelle
7
Dadurch erhalten Sie die atomare Ersetzung, obwohl Sie immer noch eine Ersetzung durchführen, anstatt sie zu bearbeiten (der neue Link hat eine neue Inode-Nummer).
Psusi
2
@psusi Ich stimme vollkommen zu, es ist nur eine technisch etwas bessere Option als die andere Antwort in einigen Szenarien.
Oli
Wenn Sie den Link zu einem anderen Ziel umleiten, erscheint die Änderung der Inode-Nummer als geringfügige Änderung.
ams
4
Dies setzt voraus, dass linknamees sich nicht um einen Symlink zu einem Verzeichnis handelt. Verwenden Sie die -TOption, mvum dies unter GNU oder -hunter FreeBSD zu vermeiden. Beachten Sie, ln -sfdass auf diese Weise die Berechtigungen des Links nicht erhalten bleiben (auf Systemen, auf denen sie von Bedeutung sind).
Stéphane Chazelas
Eine andere Lösung zum Ändern des Symlinks für das Verzeichnis besteht darin, -nOptionen zu verwenden , z ln -sfn DESTINATION_DIRECTORY LINK_NAME. Lesen Sie mehr auf askubuntu.com/a/186227/69004
sobi3ch
22

Wenn Sie durch Bearbeiten die Datei ändern möchten, auf die sie verweist, können Sie:

$ 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

Der -fParameter ( --force) , wenn übergeben ln es bewirkt , dass es das nennen unlink()Systemaufruf direkt vorsymlink()

Entnommen aus der folgenden Stapelüberlaufantwort .

NlightNFotis
quelle
9
Ich halte es für fraglich, ob dies als "Bearbeiten" angesehen werden kann, da unlink (); symlink (); ist nicht atomar, daher gibt es eine winzige Zeitspanne, in der die Verknüpfung nicht existiert.
Wiederholung
@ mauro.stettler Ja, du hast recht. Aber ich denke, das hängt von Ihrer Perspektive ab. Wenn Sie nur das Endergebnis berücksichtigen, können Sie es möglicherweise als bearbeitet betrachten, ohne dass andere Aspekte berücksichtigt werden.
NlightNFotis
1
Der zitierte Abschnitt aus dem Unix - Time Sharing - System Papier beschreibt harte Links. Diese unterscheiden sich grundlegend von den symbolischen Links (Symlinks), nach denen das OP gefragt hat.
Ansgar Esztermann
4
Beachten Sie, dass davon ausgegangen wird test, dass das Ziel kein Verzeichnis ist. Andernfalls ln -s -f .profile testwürde ein .profileSymlink in diesem Verzeichnis erstellt. GNU lnhat eine -TOption, dies zu vermeiden.
Stéphane Chazelas
9

Symbolische Links müssen atomar modifiziert werden. Wenn Sie auf halbem Weg sind, werden sie nicht funktionieren. Der Inhalt eines symbolischen Links ist ziemlich klein (höchstens 4095 Zeichen unter Linux: die maximale Länge eines Pfads zu einer Datei), sodass es wenig Sinn macht, einen Teil eines symbolischen Links auf Kernelebene zu bearbeiten. Daher bietet der Kernel keine Schnittstelle zum Bearbeiten eines symbolischen Links, nur eine Schnittstelle zum Erstellen eines neuen Links, den symlinkSystemaufruf (plus die allgemeine Schnittstelle unlinkzum Entfernen von Dateien).

Der symlinkSystemaufruf erstellt nur eine neue symbolische Verknüpfung, entfernt jedoch keine vorhandene Datei. Dies ist ärgerlich, aber im Einklang mit anderen Systemaufrufen zum Erstellen von Dateien wie open(die eine neue Datei erstellen oder eine vorhandene Datei abschneiden, eine vorhandene Datei jedoch nicht durch eine neu erstellte Datei ersetzen können) und mkdir.

In der Shell können Sie , wie Sie festgestellt haben , einen symbolischen Link nicht atomar durch den lnBefehl ersetzen ( ln -sfindem Sie die Verknüpfung der vorherigen Datei aufheben und dann den symbolischen Link erstellen). Dazu müssen Sie zunächst einen symbolischen Link unter einem temporären Namen und erstellen dann verschieben Sie es in Position.

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
Gilles 'SO - hör auf böse zu sein'
quelle
2
mv -f(wie ln -sf) wird nicht tun, was Sie wollen, wenn $linkauf ein Verzeichnis verweist. GNU ln und mv haben ein -Tdafür. mv(Systemaufruf umbenennen) ändert immer den Inode von $linkwhile ln -sfT(Unlink + Symlink).
Stéphane Chazelas
0

Technisch gibt es keinen eingebauten Befehl zum Bearbeiten einer vorhandenen symbolischen Verknüpfung. Es kann leicht mit ein paar kurzen Befehlen erreicht werden.

Hier ist eine kleine Bash / Zsh-Funktion, die ich geschrieben habe, um einen vorhandenen symbolischen Link zu aktualisieren:

# -----------------------------------------
# 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
quelle
Entschuldigung, aber Ihre "Antwort" bezieht sich nur aus der Ferne auf die gestellte Frage.
user2233709
Hallo @ user2233709 - Die Frage des Benutzers " Wie kann ich Symlinks bearbeiten? " Wurde sowohl im ersten Satz als auch durch die Bereitstellung einer Lösung eindeutig beantwortet. Möchten Sie näher darauf eingehen?
Blizzrdof77
2
Hast du die Frage wirklich gelesen? Es geht darum, ob es möglich ist, einen Symlink zu ändern , anstatt ihn zu ersetzen . Ihre vorgeschlagene "Lösung" ist ein Skript, das einen Symlink ersetzt.
user2233709
0

Angenommen, der Linkname existiert als Ergebnis dessen, was (in der Vergangenheit) getan wurde:

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

Dann gibt es drei Möglichkeiten, den Symlink zu ändern:

  • Verwenden Sie ln mit -fKraft und sogar für Verzeichnisse -n(Inode könnte wiederverwendet werden):

    ln -sfn /some/new/path linkname
    
  • Entfernen Sie den Symlink und erstellen Sie einen neuen (auch für Verzeichnisse):

    rm linkname; ln -s /some/new/path linkname
    
  • erstelle einen neuen symlink, dann geht mves (atomarer wechsel auch für verzeichnisse):

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