Làm thế nào để liệt kê các chuỗi liên kết tượng trưng?


36

Cho ví dụ này:

mkdir a
ln -s a b
ln -s b c
ln -s c d

Nếu tôi thực thi:

ls -l d

Nó sẽ hiển thị:

d -> c

Có cách nào để lshoặc bất kỳ lệnh linux nào khác hiển thị d -> c -> b -> athay thế?


Tôi đã đăng bài này dưới dạng stackoverflow.com/questions/2320277/ Vì tôi hy vọng bạn không phiền.
Paul

Câu trả lời:


65

Chỉ cần sử dụng namei:

$ namei d
f: d
 l d -> c
   l c -> b
     l b -> a
       d a

5
GẠCH Đây là một lệnh tuyệt vời . upvotes
Tom O'Connor

Đây phải là câu trả lời được chấp nhận, vì nó cho thấy chuỗi liên kết hoàn chỉnh theo yêu cầu trong op. Hơn nữa nó có thể được sử dụng để liệt kê toàn bộ thư mục tương tự ls. Cảm ơn!
phobic

Thật vậy, đã xem lại bài này và namei là một lệnh tuyệt vời!
Kalecser

sử dụng với lệnh "which" để tìm cách sử dụng thực tế của một chương trình: $ namei `which java`
pdem

18

readlink -e <link>

đường dẫn đọc [TÙY CHỌN] ... TẬP TIN

  • -e, --canonicalize-
    canonicalize bằng cách theo mọi symlink trong mọi thành phần của tên đã cho theo cách đệ quy, tất cả các thành phần phải tồn tại
$ mkdir testlink
$ cd testlink
pjb@pjb-desktop:~/testlink$ ln -s c b
pjb@pjb-desktop:~/testlink$ ln -s b a
pjb@pjb-desktop:~/testlink$ ls -l 
total 0
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
pjb@pjb-desktop:~/testlink$ echo foo > c
pjb@pjb-desktop:~/testlink$ cat a
foo
pjb@pjb-desktop:~/testlink$ readlink -e a
/home/pjb/testlink/c

lưu ý: readlink a tự trả về b

lưu ý số 2: cùng với find -l, một tiện ích để liệt kê các chuỗi có thể dễ dàng được viết bằng perl, nhưng cũng phải đủ thông minh để phát hiện các vòng lặp

readlink sẽ không xuất bất cứ thứ gì nếu bạn có một vòng lặp. Điều này tốt hơn là bị mắc kẹt, tôi cho rằng.

pjb@pjb-desktop:~/testlink$ ln -sf a c
pjb@pjb-desktop:~/testlink$ ls -l 
total 0
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a
pjb@pjb-desktop:~/testlink$ readlink -e a
pjb@pjb-desktop:~/testlink$ # (note: no output)

Trên OS X: brew install coreutilsgreadlink -e <link>
Jose Alban

3

Đây là một hàm đệ quy trong Bash:

chain() { export chain; local link target; if [[ -z $chain ]]; then chain="$1"; fi; link=$(stat --printf=%N $1); while [[ $link =~ \-\> ]]; do target="${link##*\`}"; target="${target%\'}"; chain+=" -> $target"; chain "$target"; return; done; echo "$chain"; unset chain; }

Trên nhiều dòng:

chain() {
    export chain
    local link target
    if [[ -z $chain ]]
    then
        chain="$1"
    fi
    link=$(stat --printf=%N "$1")
    while [[ $link =~ \-\> ]]
    do
        target="${link##*\`}"
        target="${target%\'}"
        chain+=" -> $target"
        if [[ ! $target =~ / && $1 =~ / ]]
        then
            target="${1%/*}/$target"
        fi
        chain "$target"
        return
    done
    echo "$chain"
    unset chain
}

Ví dụ:

$ chain d
d -> c -> b -> a
$ chain c
c -> b -> a
$ chain a
a

Nó đòi hỏi stat(1)có thể không có mặt trên một số hệ thống.

Nó sẽ thất bại nếu tên chứa backticks, dấu ngoặc đơn hoặc "->". Nó bị mắc kẹt trong một vòng lặp với các vòng lặp symlink (điều này có thể được giải quyết bằng cách sử dụng một mảng kết hợp trong Bash 4). Nó xuất một biến gọi là "chuỗi" mà không cần quan tâm đến việc nó đã được sử dụng chưa.

Có thể có những vấn đề khác với nó.

Chỉnh sửa:

Đã sửa lỗi với một số liên kết tương đối. Một số vẫn không hoạt động, nhưng phiên bản dưới đây không yêu cầu mục tiêu của liên kết tồn tại.

Đã thêm phiên bản sử dụng đường dẫn đọc:

chain ()
{
    export chain;
    local target;
    if [[ -z $chain ]]; then
        chain="$1";
    fi;
    target=$(readlink "$1");
    while [[ $target ]]; do
        chain+=" -> $target";
        if [[ ! $target =~ / && $1 =~ / ]]
        then
            target="${1%/*}/$target"
        fi
        chain "$target";
        return;
    done;
    echo "$chain";
    unset chain
}

Tôi đã thử kịch bản của bạn và nó thực sự hoạt động nhưng tôi thích một cái gì đó đơn giản hơn nên tôi đã chấp nhận câu trả lời khác ngay cả khi chưa hoàn thành.
Kalecser

1
Kịch bản hay. Đôi khi tôi muốn xem toàn bộ chuỗi, và readlinkdường như không cho thấy điều đó. Java trên Ubuntu là:/usr/bin/java -> /etc/alternatives/java -> /usr/lib/jvm/java-6-openjdk/jre/bin/java
Stefan Lasiewski

0

Bạn chỉ có thể xử lý hậu quả đầu ra của namei bằng một cái gì đó giống awkhoặc grepđể có được các dòng bạn muốn:

namei d | awk '$1=="l"'

hoặc là

namei d | egrep -e "->"
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.