pokaż tylko plik źródłowy i docelowy plik połączony za pomocą `ls`

11

Mogę pokazać plik docelowy, do którego prowadzi łącze 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

Czy istnieje sposób na pokazanie mniejszej mocy wyjściowej bez konieczności przepuszczania innego polecenia, takiego jak awk? Na przykład:

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

Używam wersji 3.2.53 w systemie OS X 10.9.5. Dane wyjściowe z kilku poleceń pokazano poniżej:

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
Chris Snow
źródło

Odpowiedzi:

7

lsniestety nie ma opcji pobierania atrybutów plików i wyświetlania ich w dowolny sposób. Niektóre systemy mają do tego osobne polecenia (na przykład GNU ma statpolecenie lub funkcjonalność w GNU find).

W większości nowoczesnych systemów z większością plików powinno to jednak działać:

$ 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

Działa to poprzez usunięcie pierwszych 8 pustych pól rozdzielanych z pierwszego wiersza wyniku ls -l. Powinno to działać, z wyjątkiem systemów, w których gid nie jest tam wyświetlany lub pierwsze 2 pola są połączone razem, gdy istnieje duża liczba łączy.

Z GNU stat:

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

Z GNU find:

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

Ze statystyką FreeBSD / OS / X:

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

Ze zshstat:

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

Wiele systemów ma również readlinkpolecenie, aby konkretnie uzyskać cel łącza:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi
Stéphane Chazelas
źródło
stat -f "%N -> %Y" -- /usr/local/bin/mvndziałało świetnie. Dzięki!
Chris Snow,
1
Na starym systemie RHEL6 stat jest GNU coreutils 8.4 i tam jest stat -c %N -- /usr/local/bin/mvn. Aby usunąć cytaty, musiałem | perl -pe 's/['"'"'`]//g'
przesłać je
@ cfi tr -d \'\`wystarczy. Zauważ, że ten system RHEL miałby GNU, finddzięki któremu będziesz mieć większą kontrolę.
Stéphane Chazelas
5

Użyj filepolecenia.

[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'

lub

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

Ponadto, przejdź przeczytać stronę man lsi sprawdzić opcje -Li -Hi sprawdzić, czy wystarczyłoby swoje wymagania.

Sree
źródło
fajnie, ucz się czegoś nowego każdego dnia.
rab
@Sree - wielkie dzięki! Próbowałem lsopcji, ale nie file. Niestety, żadne nie wydaje się działać :(
Chris Snow,
@SHC Przepraszamy, założyłem, że jesteś na linuxpudełku. Dodaj osxjako jeden ze swoich tagów. Powinno to również zwrócić uwagę osxużytkowników. Zredagowałem post, aby dodać tag, ale nie mam wystarczających napisów, aby zmiana pojawiła się natychmiast.
Sree,
@ Sree - nie martw się i przepraszam za zamieszanie. I tak głosowałem twoją odpowiedź, ponieważ będzie ona przydatna, gdy wrócę na maszynę z systemem Linux.
Chris Snow,
może sprawdź narzędzie „readlink” na osx.
tonioc
2

Przy pomocy GNU lsprzynajmniej (i najwyraźniej tcshimplementacji) możesz zhakować $LS_COLORSzmienną środowiskową, aby wstawić separatory tam, gdzie chcesz (ale tcshwbudowane ls-Fnie robi celów link - tylko flagi link ) Zwykle lswstawia dowolne znaki niedrukowalne terminala oparte na wartościach przechowywanych w tym środowisku var, ale nic nie powstrzymuje nas przed wstawieniem arbitralnego czegokolwiek innego. Więcej na ten temat tutaj .

Na przykład:

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

To umieszcza ciąg jak //na początku każdego wpisu (czyli tuż przed lrwcrwx) i ///\ntuż przed nazwą pliku dowolnego linku. sednastępnie filtruje zakresy linii - usunie dkażdą linię wejściową, aż napotka, ///a stamtąd przez następny //pasujący wiersz usunie pasujące linie //. Otrzymuje więc tylko nazwę i cel linku - niezależnie od interweniujących postaci. Wynika to z faktu, /że nazwa pliku nie może wystąpić - a osoby z dowolnej ścieżki lsmogą drukować tylko pojedynczo.

Widzieć?

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'

... który drukuje:

long


name.ln -> long


name
shortname.ln -> shortname

Spróbuj sam.

mikeserv
źródło
Czy znasz jakieś implementacje poza nowoczesnymi wersjami GNU, lsktóre obsługują LS_COLORSten sposób --color=alwaysoraz opcje i po argumentach? Jeśli w systemie GNU, dlaczego miałbyś używać czegoś, co byłoby skomplikowane, kiedy możesz użyć findlub stat? To też prawdopodobnie nie zadziała, jeśli coś zrobisz ln -s /// some-file.
Stéphane Chazelas,
@StephaneChezales - oznacza to przynajmniej, że powinien działać podobnie z bsd ls. Pamiętam, że czytałem to gdzieś kilka miesięcy temu o tym, lsże wszyscy akceptują składnię typu termcap. Dobra uwaga na ten temat ln -s ///- ale \0NUL działają również - i -Rekscytująco. Co do tego - cóż, jest łatwy w użyciu. W niektórych przypadkach łatwiej niż find- i wydawało się tutaj, że jest trochę więcej na ten temat, niż findbyłoby. W każdym razie nie myśli o tym zbyt wiele osób, więc wspominam o tym, gdy mi przypominają.
mikeserv
Zobacz stronę podręcznika lub tam dla FreeBSD. Jeśli chcesz przetestować rzeczy na FreeBSD, możesz używać wirtualnych płyt CD, takich jak GhostBSD / mfsbsd na maszynie wirtualnej.
Stéphane Chazelas,
@ StéphaneChazelas - nie, nie muszę tego testować - zdecydowanie zupełnie inne zwierzę . Jeśli chcesz spojrzeć, źródło GNU jest również powiązane z linkiem w tej odpowiedzi. zastanawiam się, gdzie czytam tę inną rzecz? bardzo dziękuję za zwrócenie uwagi na to, że było to błędne założenie, które z radością odrzucę. zredagowałem odpowiedź.
mikeserv
najnowsze wersje tcshmają ls-Fwbudowane, które obsługuje LS_COLORStak samo, jak niektóre wersje GNU ls, ale ucieka się do wywoływania, ls -Fjeśli przekażesz mu jakąkolwiek opcję, więc nie będzie działać tutaj, chyba że lsGNU jest lsw twoim systemie.
Stéphane Chazelas,
-1

[W systemie Linux / Bash]

Zrobiłbym to:

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

sedKomenda zapada wielokrotne spacje w jednej przestrzeni; cutpobiera pole 9-r, w którym pole separatora jest przestrzeń.

Typowe wyjście z tego:

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

Alternatywami są:

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

Ale te są niedoskonałe: pierwsze może generować końcowe spacje; druga wiodąca przestrzeń.

Rabarbar
źródło
Pytanie wyraźnie brzmiało: „... bez konieczności przepuszczania innego polecenia ...”
Jeff Schaller
@JeffSchaller: Good point; Zgadzam się. Mam jednak nadzieję, że nadal przydaje się to komuś, kto chce uzyskać odpowiedź na pytanie tytułowe (bez szczegółów w opisie).
Rhubbarb