Jak mogę edytować dowiązania symboliczne?


64

Moje podstawowe rozumienie dowiązania symbolicznego to specjalny plik, plik zawierający ścieżkę łańcucha do innego pliku. VFS jądra pobiera wiele z tego, ale czy istnieje jakiś powód, dla którego dowiązania symboliczne wydają się niemożliwe do edycji?

Innymi słowy: czy mogę edytować dowiązanie symboliczne? Jeśli nie, dlaczego nie?


Rozumiem, że istnieją różne sposoby zastępowania dowiązań symbolicznych (dwie alternatywy znajdują się obecnie w sekcji odpowiedzi), ale interesujące byłoby wyjaśnienie, dlaczego wymiana wydaje się jedynym sposobem radzenia sobie z dowiązaniami symbolicznymi. Dlaczego nie możesz po prostu zmienić miejsca, w którym wskazują?


Twoje zrozumienie jest nieco ograniczone; jedynym powodem, który nazywa się „plikiem”, jest to, że nie ma na to lepszego słowa.
Shadur

5
W przeciwieństwie do krępującego okrucieństwa, jakim jest wariant systemu Windows, dowiązania symboliczne w stylu posix działają na / w samej warstwie systemu plików. Jedynym sposobem edycji jest bezpośrednia edycja systemu plików - i na ogół nie jest tego warta.
Shadur

Pliki @Shadur .lnk na początku nie są tak naprawdę dowiązaniami symbolicznymi (a NTFS ma odpowiednie dowiązania symboliczne od czasu Vista); są bardziej jak skróty do wykonywania poleceń, niezależnie od tego, czy zmienia się to w konkretny folder, czy uruchamia program z określonymi argumentami i określonym CWD.
JAB

Odpowiedzi:


36

Ponieważ -fpo prostu wykonuje cichą zamianę, możesz wykonać zamianę atomową za pomocą mv -T(-T sprawia, że ​​działa, nawet jeśli /loc.../link jest katalogiem) :

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

linkname jest dostępny przez cały proces.


7
To daje ci atomową zamianę, chociaż nadal dokonujesz zamiany zamiast edycji (nowy link ma nowy numer i-węzła).
psusi

2
@psusi Całkowicie się zgadzam, jest to tylko technicznie nieco lepsza opcja niż inna odpowiedź w niektórych scenariuszach.
Oli

Jeśli przekierowujesz link do innego miejsca docelowego, zmiana jego numeru i-węzła wydaje się niewielką zmianą.
ams

4
Zakłada linknamesię, że nie jest to dowiązanie symboliczne do katalogu. Użyj -Topcji, aby mvna GNU lub -hna FreeBSD, aby tego uniknąć. Pamiętaj, że w ln -sften sposób nie zachowuje uprawnień do łącza (w systemach, w których są one znaczące).
Stéphane Chazelas

Innym rozwiązaniem zmiany dowiązania symbolicznego do katalogu jest użycie -nopcji np ln -sfn DESTINATION_DIRECTORY LINK_NAME. : Czytaj więcej na askubuntu.com/a/186227/69004
sobi3ch

22

Jeśli przez edycję chcesz zmienić plik, na który wskazuje, to tak, możesz:

$ 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

-fParametr ( --force), gdy przeszedł do ln powoduje go wezwać unlink()tuż przed wywołanie systemowesymlink()

Zaczerpnięte z poniższej odpowiedzi przepełnienia stosu .


9
Myślę, że jest wątpliwe, czy można to uznać za „edytuj”, ponieważ unlink (); symlink (); nie jest atomowy, więc istnieje niewielka ilość czasu, przez który połączenie nie istnieje.
powtórka

@ mauro.stettler Tak, masz rację. Ale myślę, że to zależy od twojej perspektywy. Jeśli weźmiesz pod uwagę tylko wynik końcowy, być może możesz uznać go za zredagowany, bez innych rozważań.
NlightNFotis

1
Cytowana sekcja z dokumentu Unix Time Sharing System opisuje twarde linki. Różnią się one całkowicie od dowiązań symbolicznych (dowiązań symbolicznych), o które pytał PO.
Ansgar Esztermann

4
Zauważ, że zakłada test, że celem nie jest katalog. W przeciwnym razie ln -s -f .profile testutworzyłby .profiledowiązanie symboliczne w tym katalogu. GNU lnma -Topcję, aby tego uniknąć.
Stéphane Chazelas

9

Łącza symboliczne należy zmodyfikować atomowo. Jeśli jesteś w połowie pisania, nie będą działać. Treść dowiązania symbolicznego jest dość mała (maksymalnie 4095 znaków w Linuksie: maksymalna długość ścieżki do pliku), więc nie ma sensu edytować części dowiązania symbolicznego na poziomie jądra. Dlatego jądro nie oferuje żadnego interfejsu do edycji dowiązania symbolicznego, tylko interfejs do tworzenia nowego, symlinkwywołania systemowego (plus ogólny interfejs unlinkdo usuwania dowolnego pliku).

symlinkWywołanie systemowe tylko tworzy nowy link symboliczny, nie usunąć istniejący plik. Jest to denerwujące, ale spójne z innymi wywołaniami systemowymi do tworzenia plików, takich jak open(które mogą utworzyć nowy plik lub skrócić istniejący plik, ale nie zastąpić istniejącego pliku nowo utworzonym plikiem) i mkdir.

Jak już odkryłeś , w powłoce nie możesz atomowo zastąpić dowiązania symbolicznego lnpoleceniem ( ln -sfrozłącza poprzedni plik, a następnie tworzy dowiązanie symboliczne), możesz to zrobić, najpierw tworząc dowiązanie symboliczne pod nazwą tymczasową i następnie przesuwając go na miejsce.

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"

2
mv -f(jak ln -sf) nie zrobi tego, co chcesz, jeśli $linkwskazuje na katalog. GNU ln i mv mają coś -Ttakiego. mv(zmiana nazwy wywołania systemowego) zawsze zmieni i-węzeł $linkwhile ln -sfT(unlink + symlink) może ponownie tego samego użyć.
Stéphane Chazelas

0

Technicznie nie ma wbudowanego polecenia do edycji istniejącego dowiązania symbolicznego. Można to łatwo osiągnąć za pomocą kilku krótkich poleceń.

Oto mała funkcja bash / zsh, którą napisałem, aby zaktualizować istniejące łącze symboliczne:

# -----------------------------------------
# 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"
}

Przepraszamy, ale „odpowiedź” dotyczy tylko zadanego pytania.
user2233709,

Cześć @ user2233709 - na pytanie użytkownika „ Jak mogę edytować dowiązania symboliczne? ” Wyraźnie odpowiedziano w pierwszym zdaniu, a także podając rozwiązanie. Czy chciałbyś opracować?
blizzrdof77

2
Czy naprawdę przeczytałeś pytanie? Chodzi o to, czy można zmodyfikować dowiązanie symboliczne, zamiast go zastąpić . Proponowane „rozwiązanie” to skrypt, który zastępuje dowiązanie symboliczne.
user2233709

0

Załóżmy, że linkname istnieje w wyniku wykonania (w przeszłości):

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

Istnieją trzy sposoby zmiany dowiązania symbolicznego:

  • Użyj ln z -fsiłą, a nawet dla katalogów -n(i-węzeł może zostać ponownie użyty):

    ln -sfn /some/new/path linkname
    
  • Usuń dowiązanie symboliczne i utwórz nowe (nawet dla katalogów):

    rm linkname; ln -s /some/new/path linkname
    
  • utwórz nowe dowiązanie symboliczne, a następnie mv(zmiana atomowa nawet dla katalogów):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.