Bagaimana saya bisa mengedit symlink?

64

Pemahaman dasar saya tentang symlink adalah sebagai file khusus, file yang berisi jalur string ke file lain. Kernel VFS mengabstraksi banyak hal itu tetapi apakah ada alasan mengapa symlink tampaknya tidak dapat diedit?

Dengan kata lain: Dapatkah saya mengedit symlink? Jika tidak, mengapa tidak?


Saya mengerti bahwa ada berbagai cara untuk mengganti symlink (dua alternatif saat ini ada di bagian jawaban) tetapi akan menarik untuk mendapatkan penjelasan tentang mengapa penggantian tampaknya menjadi satu-satunya cara untuk berurusan dengan symlink. Mengapa Anda tidak bisa mengubah di mana mereka menunjuk?

Oli
sumber
Pemahaman Anda agak terbatas; satu-satunya alasan itu disebut 'file' adalah karena tidak ada kata yang lebih baik untuk itu.
Shadur
5
Berbeda dengan kekejaman memalukan yang merupakan varian windows, tautan simbolik gaya posix beroperasi pada / di lapisan sistem berkas itu sendiri. Satu-satunya cara untuk mengedit satu akan mengedit sistem file secara langsung - dan itu umumnya tidak sepadan.
Shadur
@ Shadur .lnk file tidak benar-benar symlink untuk memulai dengan (dan NTFS memiliki symlink yang tepat sejak Vista); mereka lebih seperti jalan pintas untuk menjalankan perintah, apakah itu berubah ke folder tertentu atau memulai program dengan argumen tertentu dan dengan CWD tertentu.
JAB

Jawaban:

36

Mengingat bahwa -fhanya melakukan penggantian diam, Anda dapat melakukan penggantian atom dengan mv -T(-T membuatnya berfungsi bahkan jika /loc.../link adalah direktori) :

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

linkname dapat diakses selama proses berlangsung.

Oli
sumber
7
Itu memberi Anda penggantian atom, meskipun Anda masih melakukan penggantian alih-alih mengedit (tautan baru memiliki nomor inode baru).
psusi
2
@psusi Saya sepenuhnya setuju, itu hanya pilihan teknis yang sedikit lebih baik daripada jawaban lain dalam beberapa skenario.
Oli
Jika Anda mengarahkan ulang tautan ke tujuan lain, maka mengubah nomor inode sepertinya merupakan perubahan kecil.
ams
4
Itu menganggap linknamebukan symlink ke direktori. Gunakan -Topsi untuk mvjika pada GNU atau -hjika pada FreeBSD untuk menghindari itu. Perhatikan bahwa seperti ln -sfitu tidak mempertahankan izin tautan (pada sistem di mana mereka signifikan).
Stéphane Chazelas
Solusi lain untuk perubahan symlink untuk direktori adalah dengan menggunakan -nopsi misalnya: ln -sfn DESTINATION_DIRECTORY LINK_NAME. Baca lebih lanjut di askubuntu.com/a/186227/69004
sobi3ch
22

Jika dengan edit, Anda bermaksud mengubah file yang ditunjuknya, maka ya Anda bisa:

$ 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

The -fparameter ( --force) ketika melewati ke ln menyebabkan itu untuk memanggil unlink()system call tepat sebelumsymlink()

Diambil dari jawaban stack overflow berikut .

NlightNFotis
sumber
9
Saya pikir patut dipertanyakan apakah ini dapat dianggap sebagai "edit", karena batalkan tautan (); symlink (); bukan atom, jadi ada sejumlah kecil waktu di mana tautan tidak ada.
ulangan
@ mauro.stettler Ya, Anda benar. Tapi saya kira ini tergantung pada sudut pandang Anda. Jika Anda hanya memperhitungkan hasil akhirnya, maka mungkin Anda dapat menganggapnya sebagai hasil edit, tidak ada hal lain yang dipertimbangkan.
NlightNFotis
1
Bagian yang dikutip dari kertas Sistem Berbagi Waktu Unix menjelaskan tautan keras . Ini sepenuhnya berbeda dari tautan simbolik (symlinks) yang ditanyakan OP.
Ansgar Esztermann
4
Perhatikan bahwa ia menganggap testtarget bukan direktori. Kalau tidak, ln -s -f .profile testakan membuat .profilesymlink di direktori itu. GNU lnmemiliki -Topsi untuk menghindarinya.
Stéphane Chazelas
9

Tautan simbolik perlu dimodifikasi secara atomik. Jika Anda setengah menulis, mereka tidak akan berhasil. Konten dari tautan simbolik cukup kecil (paling banyak 4.095 karakter di Linux: panjang maksimum jalur ke sebuah file), jadi akan ada sedikit gunanya dalam mengedit bagian dari tautan simbolik di tingkat kernel. Oleh karena itu kernel tidak menawarkan antarmuka apa pun untuk mengedit tautan simbolik, hanya antarmuka untuk membuat yang baru, symlinkpanggilan sistem (plus antarmuka generik unlinkuntuk menghapus file apa pun).

The symlinksystem call hanya menciptakan link simbolik baru, itu tidak menghapus file yang ada. Ini menjengkelkan, tetapi konsisten dengan panggilan sistem lain untuk membuat file seperti open(yang dapat membuat file baru atau memotong file yang ada, tetapi tidak mengganti file yang ada dengan file yang baru dibuat) dan mkdir.

Dalam shell, seperti yang Anda temukan , sementara Anda tidak dapat mengganti tautan simbol secara atomik dengan lnperintah ( ln -sfmemutuskan tautan file sebelumnya lalu membuat tautan simbolik), Anda dapat melakukannya dengan terlebih dahulu membuat tautan simbolik di bawah nama sementara dan kemudian memindahkannya ke tempatnya.

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
mv -f(suka ln -sf) tidak akan melakukan apa yang Anda inginkan jika $linkmenunjuk ke direktori. GNU ln dan mv punya -Tuntuk itu. mv(rename system call) akan selalu mengubah inode $linksementara ln -sfT(unlink + symlink) mungkin menggunakan kembali yang sama.
Stéphane Chazelas
0

Secara teknis, tidak ada perintah bawaan untuk mengedit tautan simbolik yang ada. Itu dapat dengan mudah dicapai dengan beberapa perintah pendek.

Inilah sedikit fungsi bash / zsh yang saya tulis untuk memperbarui tautan simbolik yang ada:

# -----------------------------------------
# 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
sumber
Maaf, tetapi Anda "menjawab" hanya terkait dengan pertanyaan yang diajukan.
user2233709
Hai @ user2233709 - pertanyaan pengguna " Bagaimana saya bisa mengedit symlink? " Dijawab dengan jelas dalam kalimat pertama serta dengan memberikan solusi. Apakah Anda peduli untuk menguraikan?
blizzrdof77
2
Apakah Anda benar-benar membaca pertanyaannya? Ini tentang apakah mungkin untuk mengubah symlink, daripada menggantinya . "Solusi" yang Anda usulkan adalah skrip yang menggantikan symlink.
user2233709
0

Asumsikan linkname ada sebagai hasil dari yang telah dilakukan (di masa lalu):

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

Lalu, ada tiga cara untuk mengubah symlink:

  • Gunakan ln dengan -fpaksa dan bahkan untuk direktori -n(inode bisa digunakan kembali):

    ln -sfn /some/new/path linkname
    
  • Hapus symlink dan buat yang baru (bahkan untuk direktori):

    rm linkname; ln -s /some/new/path linkname
    
  • buat symlink baru, lalu mv(perubahan atom bahkan untuk direktori):

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