ฉันจะแก้ไขลิงก์ได้อย่างไร


64

ความเข้าใจพื้นฐานของฉันเกี่ยวกับ symlink เป็นไฟล์พิเศษไฟล์ที่มีเส้นทางสตริงไปยังไฟล์อื่น VFS ของเคอร์เนลมีจำนวนมากออกไป แต่มีเหตุผลใดที่ symlink ดูเหมือนจะเป็นไปไม่ได้ที่จะแก้ไข?

กล่าวอีกนัยหนึ่ง: ฉันสามารถแก้ไข symlink ได้หรือไม่ ถ้าไม่ทำไมไม่


ฉันเข้าใจว่ามีหลายวิธีในการแทนที่ symlinks (ปัจจุบันมีสองทางเลือกในส่วนคำตอบ) แต่มันน่าสนใจที่จะได้รับคำอธิบายว่าทำไมการแทนที่จึงดูเหมือนจะเป็นวิธีเดียวที่จะจัดการกับ symlink ทำไมคุณไม่เปลี่ยนจุดที่พวกมันชี้ไป?


ความเข้าใจของคุณค่อนข้าง จำกัด เหตุผลเดียวที่เรียกว่า 'ไฟล์' เป็นเพราะไม่มีคำที่ดีกว่า
Shadur

5
ซึ่งแตกต่างจากความโหดร้ายที่น่าอายที่เป็นตัวแปร Windows, การเชื่อมโยงสัญลักษณ์แบบ posix ทำงานบน / ในชั้นของระบบแฟ้มตัวเอง วิธีเดียวที่จะแก้ไขหนึ่งคือการแก้ไขระบบไฟล์โดยตรง - และโดยทั่วไปจะไม่คุ้มค่า
Shadur

@Shadur .lnk ไฟล์ไม่ใช่ symlink ที่เริ่มต้นด้วย (และ NTFS นั้นมี symlink ที่เหมาะสมตั้งแต่ 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
นั่นทำให้คุณได้รับการแทนที่อะตอมแม้ว่าคุณจะยังคงทำการแทนที่มากกว่าแก้ไข (ลิงก์ใหม่มีหมายเลขไอโหนดใหม่)
psusi

2
@psusi ฉันเห็นด้วยอย่างสมบูรณ์มันเป็นเพียงตัวเลือกที่ดีกว่าในทางเทคนิคเล็กน้อยกว่าคำตอบอื่น ๆ ในบางสถานการณ์
Oli

หากคุณเปลี่ยนเส้นทางลิงก์ไปยังปลายทางอื่นการเปลี่ยนแปลงหมายเลขไอโหนดดูเหมือนจะเป็นการเปลี่ยนแปลงเล็กน้อย
ams

4
สมมติว่าlinknameไม่ใช่ symlink ไปยังไดเรกทอรี ใช้-Tตัวเลือกเพื่อmvถ้าบน GNU หรือ-hถ้าบน FreeBSD เพื่อหลีกเลี่ยงปัญหานั้น โปรดทราบว่าเช่นln -sfนั้นจะไม่สงวนสิทธิ์ของลิงก์ (ในระบบที่มีความสำคัญ)
Stéphane Chazelas

อีกวิธีหนึ่งสำหรับการเปลี่ยน symlink สำหรับไดเรกทอรีคือการใช้-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) เมื่อผ่านไป LN มันทำให้เกิดการเรียกunlink()สายระบบที่ถูกต้องก่อนsymlink()

ที่นำมาจากต่อไปนี้สแต็คคำตอบล้น


9
ฉันคิดว่ามันน่าสงสัยหากสิ่งนี้ถือได้ว่า "แก้ไข" เนื่องจากยกเลิกการเชื่อมโยง (); symlink (); ไม่ใช่อะตอมจึงมีเวลาเล็กน้อยในช่วงที่ไม่มีลิงก์
เล่นซ้ำ

@ mauro.stettler ใช่คุณพูดถูก แต่ฉันเดาว่ามันขึ้นอยู่กับมุมมองของคุณ หากคุณพิจารณาผลลัพธ์สุดท้ายเท่านั้นคุณอาจพิจารณาว่าเป็นสิ่งที่ถูกแก้ไขแล้วไม่มีสิ่งอื่นใดที่จะต้องพิจารณา
NlightNFotis

1
ส่วนที่ยกมาจากกระดาษระบบ Unix Time Sharing อธิบายการเชื่อมโยงอย่างหนัก สิ่งเหล่านี้ต่างจากลิงก์สัญลักษณ์ (symlink) ที่ OP ถามเกี่ยวกับ
Ansgar Esztermann

4
โปรดทราบว่ามันถือว่าtestเป้าหมายไม่ใช่ไดเรกทอรี มิฉะนั้นln -s -f .profile testจะสร้าง.profilesymlink ในไดเรกทอรีนั้น GNU lnมี-Tตัวเลือกให้หลีกเลี่ยงสิ่งนั้น
Stéphane Chazelas

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(เปลี่ยนชื่อการโทรของระบบ) จะเปลี่ยน inode ของเสมอใน$linkขณะที่ln -sfT(unlink + symlink) อาจนำมาใช้ซ้ำ
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"
}

ขออภัย แต่คุณ“ ตอบ” นั้นเกี่ยวข้องกับคำถามที่ถามทางไกลเท่านั้น
user2233709

สวัสดี @ user2233709 - คำถามของผู้ใช้ " ฉันจะแก้ไข symlink ได้อย่างไร " ได้รับคำตอบอย่างชัดเจนในประโยคแรกและให้คำตอบ คุณสนใจที่จะทำอย่างละเอียดหรือไม่
blizzrdof77

2
คุณอ่านคำถามจริงๆหรือ มันเป็นเรื่องไม่ว่าจะเป็นไปได้ที่จะปรับเปลี่ยน symlink มากกว่าแทนที่มัน “ โซลูชัน” ที่คุณเสนอคือสคริปต์ที่แทนที่ symlink
user2233709

0

ถือว่า linkname มีอยู่เนื่องจากผลลัพธ์ของการทำ (ในอดีต):

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

จากนั้นมีสามวิธีในการเปลี่ยน symlink:

  • ใช้ ln ด้วย-fแรงและแม้กระทั่งไดเรกทอรี-n(inode สามารถนำมาใช้ซ้ำ):

    ln -sfn /some/new/path linkname
    
  • ลบ symlink และสร้างใหม่ (แม้สำหรับไดเรกทอรี):

    rm linkname; ln -s /some/new/path linkname
    
  • สร้าง symlink ใหม่จากนั้นสร้างmvมัน (การเปลี่ยนแปลงอะตอมแม้สำหรับไดเรกทอรี):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.