chỉ hiển thị tệp nguồn và tệp được liên kết đích bằng cách sử dụng `ls`


11

Tôi có thể hiển thị tệp mục tiêu mà một liên kết trỏ đến bằng cách sử dụng ls -l:

snowch$ ls -l /usr/local/bin/mvn
lrwxr-xr-x  1 snowch  admin  29 12 Dec 08:58 /usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

Có cách nào để hiển thị đầu ra ít hơn mà không phải chuyển qua một lệnh khác như awk không? Ví dụ:

snowch$ ls ?? /usr/local/bin/mvn
/usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

Tôi đang chạy 3.2.53 trên OS X 10.9.5. Đầu ra từ một số lệnh được hiển thị dưới đây:

snowch$ ls -H /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ ls -L /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ file /usr/local/bin/mvn
/usr/local/bin/mvn: POSIX shell script text executable

snowch$ file -b /usr/local/bin/mvn
POSIX shell script text executable

Câu trả lời:


7

lsThật không may, không có tùy chọn để truy xuất các thuộc tính tệp và hiển thị chúng theo cách tùy ý. Một số hệ thống có các lệnh riêng cho điều đó (ví dụ GNU có statlệnh hoặc chức năng trong GNU find).

Trên hầu hết các hệ thống hiện đại, với hầu hết các tệp, điều này sẽ hoạt động:

$ ln -s '/foo/bar -> baz' the-file
$ LC_ALL=C ls -ldn the-file | sed '
   1s/^\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{8\}//'
the-file -> /foo/bar -> baz

Điều đó hoạt động bằng cách loại bỏ 8 trường phân tách trống đầu tiên của dòng đầu tiên của đầu ra ls -l. Điều đó sẽ hoạt động ngoại trừ trên các hệ thống mà gid không được hiển thị ở đó hoặc 2 trường đầu tiên được nối với nhau khi có một số lượng lớn các liên kết.

Với GNU stat:

$ LC_ALL=C stat -c '%N' the-file
'the-file' -> '/foo/bar -> baz'

Với GNU find:

$ find the-file -prune \( -type l -printf '%p -> %l\n' -o -printf '%p\n' \)
the-file -> /foo/bar -> baz

Với chỉ số FreeBSD / OS / X:

f=the-file
if [ -L "$f" ]; then
  stat -f "%N -> %Y" -- "$f"
else
  printf '%s\n' "$f"
fi

Với zshsố liệu thống kê:

zmodload zsh/stat
f=the-file
zstat -LH s -- "$f"
printf '%s\n' ${s[link]:-$f}

Nhiều hệ thống cũng có một readlinklệnh để đặc biệt nhận được mục tiêu của một liên kết:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi

stat -f "%N -> %Y" -- /usr/local/bin/mvnlàm việc tuyệt vời Cảm ơn!
Chris Snow

1
Trên một hệ thống RHEL6 cũ, stat là của GNU coreutils 8.4 và có nó stat -c %N -- /usr/local/bin/mvn. Để xóa các trích dẫn, tôi phải chuyển nó thành| perl -pe 's/['"'"'`]//g'
cfi

@cfi tr -d \'\`sẽ là đủ. Lưu ý rằng hệ thống RHEL sẽ có GNU findmà bạn sẽ có quyền kiểm soát nhiều hơn.
Stéphane Chazelas

5

Sử dụng filelệnh.

[sreeraj@server ~]$ ls -l mytest
lrwxrwxrwx 1 sreeraj sreeraj 15 Dec 12 09:31 mytest -> /usr/sbin/httpd

[sreeraj@server ~]$ file mytest
mytest: symbolic link to `/usr/sbin/httpd'

hoặc là

[sreeraj@server ~]$ file -b mytest
symbolic link to `/usr/sbin/httpd'
[sreeraj@server ~]$

Ngoài ra, xin vui lòng đi đọc qua trang người đàn ông của lsvà đánh dấu vào tùy chọn -L-Hvà xem nếu mà có đủ yêu cầu của bạn.


tuyệt, học một cái gì đó mới mỗi ngày.
cướp

@Sree - Rất cám ơn! Tôi đã thử các lstùy chọn, nhưng không file. Thật không may, dường như không hoạt động :(
Chris Snow

@SHC Xin lỗi, tôi giả sử rằng bạn đang ở trên một linuxhộp. Vui lòng thêm osxdưới dạng một trong các thẻ của bạn. Điều đó cũng sẽ nhận được sự chú ý của osxngười dùng. Tôi đã chỉnh sửa bài đăng để thêm thẻ, nhưng tôi không có đủ tín dụng để chỉnh sửa xuất hiện ngay lập tức.
Sree

@Sree - không phải lo lắng, và xin lỗi vì sự nhầm lẫn. Dù sao tôi cũng đã đưa ra câu trả lời của bạn vì nó sẽ hữu ích khi tôi quay lại máy linux.
Chris Snow

có thể kiểm tra tiện ích 'readlink' trên osx.
tonioc

2

Với GNU lsít nhất (và, rõ ràng tcshlà triển khai), bạn có thể hack $LS_COLORSbiến môi trường để chèn dấu phân cách vào nơi bạn thích (nhưng tcshnội dung dựng sẵn ls-Fkhông thực hiện các mục tiêu liên kết - chỉ các cờ liên kết ) Thường lschèn các thiết bị đầu cuối không thể in tùy ý dựa trên các giá trị được lưu trữ trong var môi trường đó, nhưng không có gì ngăn chúng ta chèn bất cứ thứ gì khác tùy ý. Thêm về điều này ở đây .

Ví dụ:

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls ~ -l --color=always | 
sed '\|///|,\|//|!d;//d'

Điều đó đặt một chuỗi như //ở đầu mỗi danh sách (vì vậy ngay trước đó lrwcrwx)///\nngay trước tên tệp của bất kỳ liên kết nào. sedsau đó lọc trên phạm vi dòng - nó sẽ dxóa mọi dòng đầu vào cho đến khi nó gặp ///và từ đó qua dòng tiếp theo khớp với //nó sẽ xóa các dòng khớp //. Vì vậy, nó chỉ nhận được tên liên kết và mục tiêu liên kết - bất kể các ký tự can thiệp. Điều này là do /không thể xảy ra trong một tên tệp - và những người trong bất kỳ đường dẫn nào lscó thể in sẽ chỉ xảy ra đơn lẻ.

Xem?

mkdir test; cd test
touch 'long


name' shortname
ln -s l* "$(printf %s.ln l*)"; ln -s s* shortname.ln

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls  -l --color=always | sed '\|///|,\|//|!d;//d'

... mà in:

long


name.ln -> long


name
shortname.ln -> shortname

Hãy thử nó.


Bạn có biết về bất kỳ triển khai nào ngoài các phiên bản hiện đại của GNU lshỗ trợ LS_COLORStheo cách đó và a --color=alwaysvà các tùy chọn sau các đối số không? Nếu trên hệ thống GNU, tại sao bạn lại sử dụng thứ gì đó phức tạp khi bạn có thể sử dụng findhoặc stat? Điều đó cũng có thể sẽ không hoạt động nếu bạn làm một số ln -s /// some-file.
Stéphane Chazelas

@StephaneChezales - điều này ít nhất cho thấy rằng nó sẽ hoạt động tương tự với một bsd ls. Tôi nhớ rằng đã đọc ở đâu đó vài tháng trước về lstất cả các xu hướng chấp nhận một cú pháp như thuật ngữ. Điểm hay về ln -s ///điều này - nhưng NUL \0cũng hoạt động tốt - và -Rsinh động. Về lý do - tốt, nó dễ sử dụng. Trong một số trường hợp dễ dàng hơn find- và dường như chủ đề ở đây nhiều hơn một chút find. Trong mọi trường hợp, không có quá nhiều người xem xét nó, vì vậy tôi đề cập đến nó khi tôi được nhắc nhở.
mikeerv

Xem trang người đàn ông hoặc ở đó cho FreeBSD. Nếu bạn muốn kiểm tra mọi thứ trên FreeBSD, bạn có thể sử dụng các đĩa CD trực tiếp như GhostBSD / mfsbsd trong VM.
Stéphane Chazelas

@ StéphaneChazelas - không, tôi không cần kiểm tra nó - chắc chắn là một loài động vật hoàn toàn khác . Nếu bạn quan tâm để tìm kiếm, nguồn gnu cũng được liên kết đến trong liên kết trong câu trả lời này. tôi tự hỏi tôi đã đọc thứ khác ở đâu? cảm ơn rất nhiều vì đã chỉ ra rằng mặc dù, đó là một giả định sai lầm tôi rất vui khi loại bỏ. ive đã chỉnh sửa câu trả lời.
mikeerv

các phiên bản gần đây tcshcó một ls-Fnội dung hỗ trợ LS_COLORSgiống như một số phiên bản GNU ls, nhưng nó dùng để gọi ls -Fnếu bạn chuyển bất kỳ tùy chọn nào cho nó, do đó sẽ không hoạt động ở đây trừ khi lsGNU lstrên hệ thống của bạn.
Stéphane Chazelas

-1

[Trên Linux / Bash]

Tôi sẽ làm điều này:

ls -l | sed -e"s/ \+/ /g" | cut -d' ' -f 9-

Các sedlệnh sụp đổ nhiều không gian để một không gian duy nhất; các cutchất chiết xuất từ các lĩnh vực thứ 9 trở đi nơi trường tách là một không gian.

Đầu ra điển hình từ đây:

libboost_atomic.a
libboost_atomic.so -> libboost_atomic.so.1.57.0
libboost_atomic.so.1.57.0
...
libboost_wserialization.a
libboost_wserialization.so -> libboost_wserialization.so.1.57.0
libboost_wserialization.so.1.57.0

Các lựa chọn thay thế là:

ls -l | awk '{ print $9, $10, $11 }'
ls -l | awk '{ $1 = $2 = $3 = $4 = $5 = $6 = $7 = $8 = "" ; print }'

Nhưng đó là những thứ không hoàn hảo: cái đầu tiên có thể tạo ra các khoảng trắng ở cuối; không gian thứ hai, hàng đầu.


Câu hỏi đã tuyên bố rõ ràng "... mà không cần phải chuyển qua lệnh khác ..."
Jeff Schaller

@JeffSchaller: Điểm tốt; Tôi đồng ý. Tuy nhiên, tôi hy vọng rằng điều này vẫn còn hữu ích cho ai đó muốn có câu trả lời cho câu hỏi tiêu đề (không có chi tiết trong mô tả).
Đại hoàng
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.