ฉันจะ“ เชื่อมโยง” symlink ที่ใช้งานไม่ได้อีกครั้งได้อย่างไร


54

ฉันมีแผนผังไดเรกทอรีที่มีลิงก์สัญลักษณ์ไปยังไฟล์ภายใต้/home... อย่างไรก็ตามฉันย้าย/homeไป/mnt/homeแล้วและต้องการวิธี "เชื่อมโยง" ลิงก์ทั้งหมดใหม่ มีฟังก์ชั่นดังกล่าวอยู่หรือฉันต้องเขียนสคริปต์เพื่อทำเช่นนั้น?

ตัวอย่างเช่นฉันมีสิ่งต่อไปนี้:

[root@trees ~]# ls -l /mnt/home/someone/something
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/e

/mnt/home/someone/something/subdir:
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/subdir/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/subdir/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/subdir/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/subdir/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/subdir/e

ฉันต้องการคำสั่งที่จะพบ symlink ทั้งหมดและเชื่อมโยงไปยังสถานที่เดียวกัน แต่อยู่ด้านล่าง/mnt/homeแทน/home

คำสั่งดังกล่าวมีอยู่จริงหรือไม่?

คำตอบ:


55

ไม่มีคำสั่งให้กำหนดลิงก์สัญลักษณ์อีกครั้งสิ่งที่คุณทำได้คือลบออกแล้วสร้างใหม่ สมมติว่าคุณมียูทิลิตี้ GNU (เช่นในลินุกซ์หรือ Cygwin ที่ไม่ใช่แบบฝัง) คุณสามารถใช้-lnameหลักของfindเพื่อจับคู่ลิงก์สัญลักษณ์ตามเป้าหมายและreadlinkเพื่ออ่านเนื้อหาของลิงค์ ยังไม่ทดลอง:

find /mnt/home/someone/something -lname '/home/someone/*' \
     -exec sh -c 'ln -snf "/mnt$(readlink "$0")" "$0"' {} \;

มันจะเป็นการดีกว่าที่จะทำให้ลิงก์สัญลักษณ์เหล่านี้สัมพันธ์กัน มียูทิลิตี้เล็ก ๆ น้อย ๆ ที่สะดวกสบายที่เรียกว่าsymlinks(แต่เดิมโดย Mark Lords ซึ่งขณะนี้ดูแลโดย J. Brandt Buckley) มีอยู่ใน Linux ดิสทริบิวชันหลายตัว ก่อนที่จะย้ายหรือหลังจากที่คุณกู้คืนลิงก์ที่ถูกต้องแล้วให้รันsymlinks -c /mnt/home/someone/somethingเพื่อแปลง symlink แบบสัมบูรณ์ทั้งหมดภายใต้ไดเรกทอรีที่ระบุไปยัง symlink แบบสัมพัทธ์เว้นแต่ว่ามันจะข้ามขอบเขตของระบบไฟล์


ไม่มีความผิดนี่เป็นสายการบินเดียวที่ยอดเยี่ยม แต่การแทนที่สายของ Bash อาจทำให้เวทมนตร์เปลี่ยนเส้นทางและอาจจะง่ายขึ้น
0xC0000022L

@STATUS_ACCESS_DENIED เป็นอย่างไร การดำเนินการของสายอักขระเดียวเท่านั้นคือการเพิ่มไป/mntยังเส้นทาง คุณไม่จำเป็นต้องดำเนินการกับสตริงใด ๆ
Gilles 'หยุดชั่วร้าย'

@Gilles: ขอโทษฉันคิดเกี่ยวกับคำพูดของคุณกับเส้นทางญาติ สำหรับตัวอย่าง "การแปล" ที่แน่นอนของคุณคุณมีสิทธิ์
0xC0000022L

13

ฉันรู้ว่านี่ไม่ใช่สิ่งที่ผู้เขียนร้องขอ แต่ดูเหมือนว่าพวกเขามีคำตอบอยู่แล้วดังนั้นฉันจึงเพิ่มสิ่งนี้สำหรับคนอื่น ๆ เช่นฉันที่สะดุดกับคำถาม

ต่อไปนี้จะช่วยในกรณีที่ต้องการโซลูชันที่มีความยืดหยุ่นมากขึ้นเช่นมีลิงก์สัญลักษณ์ที่เสียหายซึ่งสามารถแก้ไขได้โดยแทนที่ส่วนหนึ่งของเป้าหมายลิงก์สัญลักษณ์

เช่น. หลังจากเปลี่ยนชื่อผู้ใช้เพื่อแทนที่ชื่อผู้ใช้เก่าด้วยชื่อผู้ใช้ใหม่ในเป้าหมายของลิงก์จำนวนมากหลังจากการย้ายเสร็จสิ้นแล้ว สร้างสคริปต์ที่ชื่อว่า replace-simlinks ดังที่แสดงด้านล่าง:

#!/bin/bash
link=$1
# grab the target of the old link
target=$(readlink -- "$1")

# replace the first occurrence of oldusername with newusername in the target string
target=${target/oldusername/newusername}

# Test the link creation
echo ln -s -- "$target" "$link"

# If the above echo shows the correct commands are being issued, then uncomment the following lines and run the command again
#rm $link
#ln -s "$target" "$link"

และเรียกมันด้วยคำสั่งต่อไปนี้:

find /home/newusername/ -lname '/home/oldusername/*' -exec ~/bin/replace-simlinks {} \;

หวังว่าจะช่วยคนนี้

แก้ไข: ขอบคุณ Gilles สำหรับ kickstart ในสคริปต์นี้และคำแนะนำเกี่ยวกับการใช้สคริปต์ symlinks เพื่อสร้างลิงก์ที่สัมพันธ์กัน


1
ฉันพบว่าวิธีนี้ดีกว่าเพราะใช้การแทนที่สตริงซึ่งช่วยในกรณีที่คุณต้องเปลี่ยนชื่อของโฟลเดอร์ที่อยู่ตรงกลางของเส้นทาง โซลูชันยังง่ายต่อการปรับเปลี่ยนเพื่อทำการแปลงที่ซับซ้อนมากขึ้นหากต้องการ
Gallaecio

ฉันขอแนะนำให้อ้างถึงข้อโต้แย้งกับการทดแทนสตริงเนื่องจากจะต้องทำเพื่อใช้เครื่องหมายทับเช่นสำหรับเส้นทางในคำถามของ OP target=${target/"/home"/"/mnt/home"}มีประโยชน์มาก แต่ ขอบคุณ
Walter Nissen

3

สร้าง/homeเป็น symlink ไป/mnt/homeและsymlink ที่มีอยู่ทั้งหมดจะใช้ได้อีกครั้ง


2
การติดตั้งการเชื่อมโยงมักจะมีความเปราะบางน้อยกว่า symlink ในสถานการณ์ที่โปรแกรมตระหนักถึง symlink และดำเนินการแตกต่างกันไปตามความเป็นจริง ...
0xC0000022L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.