Cập nhật hàng loạt các liên kết tượng trưng đệ quy


12

Tôi có một ứng dụng web có một loạt các liên kết tượng trưng trong các thư mục con trong đó. Tôi cần di chuyển ứng dụng sang cấu trúc thư mục khác và tôi cần cập nhật tất cả các liên kết tượng trưng để trỏ đến đường dẫn mới. Ví dụ:

Dir cũ: Dir /home/user/public_html/dev
mới: /home/user/public_html/qa
Symlink cũ: /home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/dev/images
Symlink mới:/home/user/public_html/qa/multisites/slave01/images -> /home/user/public_html/qa/images

Vấn đề là có rất nhiều trong số này nằm rải rác trong các thư mục khác nhau. Làm cách nào tôi có thể tìm kiếm đệ quy từ thư mục gốc và tạo lại tất cả các liên kết tượng trưng /dev/với /qa/?

Câu trả lời:


16

Lệnh bash này sẽ làm điều đó cho bạn:

find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' -printf 'ln -nsf "$(readlink "%p" | sed s/dev/qa/)" "$(echo "%p" | sed s/dev/qa/)"\n' > script.sh

Nó sử dụng findđể xác định tất cả các tệp trong qathư mục là các liên kết tượng trưng với một mục tiêu trong devthư mục và đối với mỗi tệp, nó sẽ in ra một lệnh bash sẽ thay thế liên kết bằng một liên kết đến đường dẫn tương đương qa/. Sau khi bạn chạy nó, chỉ cần thực thi tập lệnh được tạo bằng

bash script.sh

Bạn có thể muốn kiểm tra nó bằng tay trước để đảm bảo nó hoạt động.

Đây là phiên bản dài hơn của findlệnh trên để dễ đọc hơn (mặc dù tôi không nhất thiết phải viết theo cách này trong thực tế):

SRC_DIR="/home/user/public_html/qa"
OLD_TARGET="/home/user/public_html/dev"
SUB="s/dev/qa/"

find $SRC_DIR -type l \
  -lname "$OLD_TARGET/*" -printf \
  'ln -nsf "$(readlink "%p"|sed $SUB)" "$(echo "%p"|sed $SUB)"\n'\
 > script.sh

Điều này tạo ra một script.sh trống. Và chạy lệnh find như vậy: find /home/user/public_html/qa/ -type l -lname '/home/user/public_html/dev/*' không xuất ra bất cứ thứ gì.
ggutenberg

Bạn đã nhớ để thay đổi các đường dẫn đến những người thực tế trên hệ thống tập tin của bạn, phải không? Điều gì xảy ra nếu bạn chỉ chạy find /home/usr/public_html/qa/ -type l? Nếu điều đó không tìm thấy các liên kết, một cái gì đó rất kỳ lạ đang xảy ra với hệ thống của bạn.
David Z

Có, " find /home/user/public_html/qa/ -type l" xuất ra các liên kết. Nhưng thêm tham số -lname thì nó không xuất ra bất cứ thứ gì.
ggutenberg

Trên thực tế, khi thử nghiệm thêm có vẻ như điều này đang hoạt động. Không chắc chắn những gì tôi đã làm sai ngày hôm qua, nhưng có vẻ như bây giờ ok. Cảm ơn.
ggutenberg

Hừ, lạ quá. Chà, nếu bạn từng nghĩ chuyện gì đang xảy ra, hãy bình luận ở đây. Tôi tò mò.
David Z

5

Trong trường hợp bất kỳ ai khác tìm thấy điều này khi tìm kiếm giải pháp: Tạo một tệp có tên "linkmod.sh" có chứa:

#!/bin/sh
PATTERN1=`echo "$2"`
PATTERN2=`echo "$3"`
LINKNAME=`echo "$1"`
OLDTARGET=`readlink "$1"`
NEWTARGET=`echo "$OLDTARGET" \
| sed -e 's/'"$PATTERN1"'/'"$PATTERN2"'/'`
echo ln -nsf "$NEWTARGET" "$LINKNAME"

và chạy

find . -type l -print0 | xargs -0IX echo linkmod.sh X "pattern1" "pattern2"

Bạn có thể sử dụng tùy chọn -lname trong tìm nếu cần.

LƯU Ý: bạn phải sử dụng 2x \ trong các mẫu trước bất kỳ ký tự nào yêu cầu \ in sed, vì echo loại bỏ một mẫu. Ví dụ

find . -type l -print0 | xargs -0IX echo linkmod.sh X "folder\\ name\\/file" "folder2\\ name\\/file"

Loại bỏ echodòng cuối cùng nếu các lệnh ln là chính xác.


Có thể tốt để làm rõ rằng cả hai echotrong dòng cuối cùng của kịch bảnechotrong find .. | xargs .. linkmod.sh ...chính lệnh đều cần phải được loại bỏ.
Kyle Strand

2

Tôi đã tạo một tập lệnh bash link_rename.shcho các liên kết tượng trưng đổi tên đệ quy trong một thư mục nhất định

#! /bin/bash

DIR=$1
OLD_PATTERN=$2
NEW_PATTERN=$3

while read -r line
do
    echo $line
    CUR_LINK_PATH="$(readlink "$line")"
    NEW_LINK_PATH="$CUR_LINK_PATH"  
    NEW_LINK_PATH="${NEW_LINK_PATH/"$OLD_PATTERN"/"$NEW_PATTERN"}"
    rm "$line"
    ln -s "$NEW_LINK_PATH" "$line"
done <<< $(find "$DIR" -type l)

Nó có thể được thực thi như link_rename.sh /home/human/dir link1 link2

Kịch bản có 3 đối số:

  1. Thư mục mà bạn muốn thực hiện đổi tên hàng loạt các liên kết tượng trưng
  2. Các mẫu cũ. Đây link1là mẫu cũ sẽ được thay thế
  3. Các mẫu mới. Đây link2là mẫu mới link1sẽ được thay thế

Kịch bản đọc đệ quy tất cả các liên kết tượng trưng trong thư mục bằng cách sử dụng find "$DIR" -type l và xử lý từng dòng một.

$line là liên kết tượng trưng cần được đổi tên

CUR_LINK_PATH là con đường cũ

NEW_LINK_PATH có được bằng cách thực hiện thay thế chuỗi trong đường dẫn liên kết cũ.

Symlink cũ bị loại bỏ và symlink mới được tạo bằng cách sử dụng ln -s "$NEW_LINK_PATH" "$line"


0

Cuối cùng tôi đã viết một tập lệnh PHP dòng lệnh dường như thực hiện thủ thuật.

<?php
//Run via command-line
$dir = new RecursiveDirectoryIterator('.');
foreach(new RecursiveIteratorIterator($dir) as $file) {
    //$link = readlink($file);
    if(is_link($file)) {
        $old_link = readlink($file);
        $new_link = str_ireplace("/joomla/", "/qa/", $old_link);
        if($new_link != $old_link) {
            exec('rm "'.$file.'"');
            exec('ln -fs "'.$new_link.'" "'.$file.'"');
            $new_link = readlink($file);
            if($new_link == $old_link) {
                echo $file."\t".$old_link."\t".$new_link."\n";
            }
        }
    }
}
?>
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.