Làm thế nào tôi có thể giới thiệu lại rất nhiều symlink bị hỏng?


54

Tôi có một cây thư mục có một loạt các liên kết tượng trưng đến các tệp trong /home... tuy nhiên, tôi đã chuyển /homeđến /mnt/homevà cần một cách để "phát lại" tất cả các liên kết tượng trưng. Có chức năng như vậy tồn tại hoặc tôi cần phải viết một kịch bản để làm như vậy?

Ví dụ, tôi có một cái gì đó như sau:

[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

Tôi muốn một lệnh sẽ tìm thấy tất cả các liên kết tượng trưng và chuyển đến cùng một nơi nhưng bên dưới /mnt/homethay vì/home

Liệu một lệnh như vậy tồn tại?

Câu trả lời:


55

Không có lệnh để nhắm mục tiêu lại một liên kết tượng trưng, ​​tất cả những gì bạn có thể làm là loại bỏ nó và tạo một liên kết khác. Giả sử bạn có các tiện ích GNU (ví dụ: trong Linux hoặc Cygwin không được nhúng), bạn có thể sử dụng -lnamechính của các findliên kết tượng trưng theo mục tiêu của chúng và readlinkđể đọc nội dung của liên kết. Chưa được kiểm tra:

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

Nó sẽ là tốt hơn để làm cho các liên kết tượng trưng tương đối. Có một tiện ích nhỏ tiện lợi được gọi là symlinks(ban đầu bởi Mark Lords, hiện được duy trì bởi J. Brandt Buckley), có mặt trong nhiều bản phân phối Linux. Trước khi di chuyển hoặc sau khi bạn đã khôi phục các liên kết hợp lệ như trên, hãy chạy symlinks -c /mnt/home/someone/somethingđể chuyển đổi tất cả các liên kết tuyệt đối trong thư mục được chỉ định thành các liên kết tương đối trừ khi chúng vượt qua một ranh giới hệ thống tập tin.


Không có ý xúc phạm, đây là một lớp lót tuyệt vời, nhưng sự thay thế chuỗi của Bash có thể thực hiện một số phép thuật thay đổi đường dẫn và sẽ dễ dàng hơn.
0xC0000022L

@STATUS_ACCESS_DENIED Làm sao vậy? Hoạt động chuỗi duy nhất là để thêm vào /mntmột đường dẫn; bạn không cần hoạt động chuỗi fancier hơn nối.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles: xin lỗi, tôi đã suy nghĩ nhiều hơn về nhận xét của bạn với các đường dẫn tương đối. Đối với một "bản dịch" chính xác của ví dụ của bạn, bạn tất nhiên là đúng.
0xC0000022L

13

Tôi biết đây không phải là chính xác những gì tác giả đang yêu cầu nhưng có vẻ như họ đã có câu trả lời của họ vì vậy tôi đang thêm điều này cho những người khác như tôi vấp phải câu hỏi.

Những điều sau đây sẽ giúp nếu cần một giải pháp linh hoạt hơn, chẳng hạn như có một loạt các liên kết tượng trưng bị hỏng có thể được sửa bằng cách thay thế một phần các mục tiêu của liên kết tượng trưng.

ví dụ. Sau khi thay đổi tên người dùng, để thay thế tên người dùng cũ bằng tên người dùng mới trong mục tiêu của nhiều liên kết, sau khi việc di chuyển đã được thực hiện. Tạo một tập lệnh được gọi là thay thế-simlinks hiển thị dưới đây:

#!/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"

và gọi nó bằng lệnh sau:

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

Hy vọng điều này sẽ giúp ai đó

chỉnh sửa: Cảm ơn Gilles vì ​​đã khởi động tập lệnh này và lời khuyên về việc sử dụng tập lệnh symlink để làm cho các liên kết tương đối.


1
Tôi thấy giải pháp này tốt hơn vì nó sử dụng thay thế chuỗi, giúp ích trong trường hợp bạn phải thay đổi tên của một thư mục ở giữa đường dẫn. Giải pháp cũng khá dễ dàng để sửa đổi để thực hiện các phép biến đổi phức tạp hơn nếu cần.
Gallaecio

Tôi khuyên bạn nên trích dẫn các đối số để thay thế chuỗi, vì điều đó phải được thực hiện để sử dụng dấu gạch chéo, ví dụ: đối với đường dẫn trong câu hỏi của OP. target=${target/"/home"/"/mnt/home"}Rất hữu ích, mặc dù. Cảm ơn.
Walter Nissen

3

Tạo /homenhư một liên kết tượng trưng đến /mnt/homevà tất cả các liên kết tượng trưng hiện có sẽ hoạt động trở lại.


2
Gắn kết thường có xu hướng ít dễ vỡ hơn các liên kết tượng trưng trong các tình huống trong đó các chương trình nhận thức được các liên kết tượng trưng và hành động khác nhau tùy thuộc vào thực tế ...
0xC0000022L
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.