Як я можу редагувати посилання?


64

Моє основне розуміння симпосилання - це спеціальний файл, файл, який містить шлях рядка до іншого файлу. VFS ядра резюмує багато цього, але чи є причина, чому символьні посилання здаються неможливими для редагування?

Іншими словами: Чи можна редагувати символьне посилання? Якщо ні, то чому б і ні?


Я розумію, що існують різні способи заміни символьних посилань (на даний момент у розділі відповідей є дві альтернативи), але було б цікаво отримати пояснення, чому заміна здається єдиним способом боротьби із символьними посиланнями. Чому ви не можете просто змінити місце, де вони вказують?


Ваше розуміння трохи обмежене; Єдина причина, що його називають "файлом", полягає в тому, що немає кращого слова для цього.
Шадур

5
На відміну від збентежувальної жорстокості, що є варіантом Windows, символічні посилання в стилі posix працюють на / у самому шарі файлової системи. Єдиний спосіб редагувати його - це редагування файлової системи безпосередньо - і це взагалі не варто.
Шадур

Файли @Shadur .lnk насправді не є посиланням для початку (і NTFS має належні посилання з початку Vista); вони більше схожі на ярлики для виконання команд, будь то зміна певної папки або запуск програми з певними аргументами та з певним CWD.
JAB

Відповіді:


36

З огляду на те, що -fпросто відбувається безшумна заміна, ви можете зробити заміну атома на mv -T(-T змушує його працювати, навіть якщо /loc.../link є каталогом) :

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

linkname є доступним протягом усього процесу.


7
Це дає вам атомну заміну, хоча ви все ще робите заміну, а не редагування (нове посилання має нове число inode).
psusi

2
@psusi Я повністю згоден, це просто технічно кращий варіант, ніж інша відповідь у деяких сценаріях.
Олі

Якщо ви перенаправляєте посилання на інше місце призначення, то зміна його номера inode здається невеликою зміною.
АМС

4
Це передбачає linkname, що не є символьним посиланням на каталог. Щоб уникнути цього, скористайтеся -Tопцією, mvякщо в GNU або -hна FreeBSD. Зауважте, що подібне ln -sfне зберігає дозволів посилання (на системах, де вони значні).
Стефан Шазелас

Ще одне рішенням для зміни линка для каталогу є використання -nопції , наприклад: ln -sfn DESTINATION_DIRECTORY LINK_NAME. Детальніше читайте на askubuntu.com/a/186227/69004
sobi3ch

22

Якщо під редагуванням ви маєте на увазі змінити файл, на який він вказує, то так, ви можете:

$ 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

-fПараметр ( --force) при передачі в пер це змушує його викликати unlink()системний виклик прямо передsymlink()

Взято з наступної відповіді на переповнення стека .


9
Я думаю, що сумнівно, якщо це можна вважати "редагувати", оскільки unlink (); symlink (); не є атомним, тому існує невеликий проміжок часу, протягом якого посилання не існує.
повтор

@ mauro.stettler Так, ви праві. Але я здогадуюсь, що це залежить від вашої точки зору. Якщо ви враховуєте лише кінцевий результат, то, можливо, ви могли б вважати його відредагованим, інших речей не враховувати.
NlightNFotis

1
У цитованому розділі з документа Unix Time Sharing описуються жорсткі посилання. Вони повністю відрізняються від символічних посилань (символьних посилань), про які запитувала ОП.
Ансгар Естерманн

4
Зауважте, що воно передбачає test, що ціль не є каталогом. Інакше ln -s -f .profile testбуло б створити .profileсимвольне посилання в цьому каталозі. У ГНУ lnє -Tможливість цього уникнути.
Стефан Хазелас

9

Символічні посилання потрібно змінювати атомно. Якщо ви на півдорозі пишете їх, вони не працюватимуть. Вміст символічного посилання досить малий (щонайбільше 4095 символів в Linux: максимальна довжина шляху до файлу), тому було б мало сенсу редагувати частину символічної посилання на рівні ядра. Тому ядро ​​не пропонує жодного інтерфейсу для редагування символічного посилання, лише інтерфейс для створення нового, symlinkсистемного виклику (плюс загальний інтерфейс unlinkдля видалення будь-якого файлу).

symlinkСистемний виклик тільки створює нову символічну посилання, він не видаляє існуючий файл. Це дратує, але відповідає іншим системним викликам для створення таких файлів, як open(які можуть створити новий файл або обрізати існуючий файл, але не замінити існуючий файл новоствореним файлом) та mkdir.

Як ви виявили , в оболонці, хоча ви не можете замінити символічне посилання атомно lnкомандою ( ln -sfвід’єднує попередній файл, потім створює символічне посилання), ви можете це зробити, спочатку створивши символьне посилання під тимчасовим іменем та потім переміщуючи його на місце.

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

2
mv -f(як ln -sf) не буде робити те, що ви хочете, якщо $linkвказує на каталог. GNU ln та mv мають -Tдля цього. mv(перейменувати системний виклик) завжди змінить вкладку, $linkтоді як ln -sfT(відключення + символьне посилання) може повторно використовувати те саме.
Stéphane Chazelas

0

Технічно немає вбудованої команди для редагування існуючого символічного посилання. Це легко досягти за допомогою декількох коротких команд.

Ось трохи функції bash / zsh, яку я написав для оновлення існуючого символічного посилання:

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

Вибачте, але ви "відповідь" пов'язані лише з віддаленим запитанням.
користувач2233709

Привіт @ user2233709 - на питання користувача " Як я можу редагувати посилання? " Чітко відповіли в першому реченні, а також запропонувавши рішення. Чи хотіли б ви допрацювати?
blizzrdof77

2
Ви справді читали питання? Йдеться про те, чи можна змінити симпосилання, а не замінити її. Пропоноване вами "рішення" - це сценарій, який замінює символьне посилання.
користувач2233709

0

Припустимо, ім'я посилань існує в результаті виконання (раніше):

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

Тоді є три способи зміни символьної посилання:

  • Використовуйте ln із -fсилою та навіть для каталогів -n(inode може повторно використовувати):

    ln -sfn /some/new/path linkname
    
  • Видаліть символьне посилання та створіть нове (навіть для каталогів):

    rm linkname; ln -s /some/new/path linkname
    
  • створити нове символьне посилання, тоді mvвоно (атомна зміна навіть для каталогів):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.