mostra apenas o arquivo de origem e o arquivo vinculado de destino usando `ls`

11

Eu posso mostrar o arquivo de destino que um link aponta para o uso 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

Existe uma maneira de mostrar menos saída sem precisar canalizar outro comando como o awk? Por exemplo:

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

Estou executando o 3.2.53 no OS X 10.9.5. A saída de vários comandos é mostrada abaixo:

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
fonte

Respostas:

7

lsinfelizmente não tem uma opção para recuperar atributos de arquivo e exibi-los de maneira arbitrária. Alguns sistemas possuem comandos separados para isso (por exemplo, o GNU possui um statcomando ou a funcionalidade no GNU find).

Na maioria dos sistemas modernos, com a maioria dos arquivos, isso deve funcionar:

$ 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

Isso funciona removendo os 8 primeiros campos delimitados em branco da primeira linha da saída de ls -l. Isso deve funcionar, exceto nos sistemas em que o gid não é exibido lá ou os dois primeiros campos são unidos quando há um grande número de links.

Com o GNU stat:

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

Com o GNU find:

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

Com o FreeBSD / OS / X stat:

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

Com zshstat:

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

Muitos sistemas também têm um readlinkcomando para obter especificamente o destino de um link:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi
Stéphane Chazelas
fonte
stat -f "%N -> %Y" -- /usr/local/bin/mvnfuncionou muito bem. Obrigado!
Chris Neve
1
Em um sistema RHEL6 antigo, o stat é do GNU coreutils 8.4 e existe um stat -c %N -- /usr/local/bin/mvn. Para remover as citações, tive que canalizar isso para dentro| perl -pe 's/['"'"'`]//g'
cfi
@cfi tr -d \'\`seria suficiente. Observe que esse sistema RHEL teria GNU findcom o qual você terá mais controle.
Stéphane Chazelas 31/08/16
5

Use o filecomando

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

ou

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

Além disso, por favor, vá ler página homem de lse verificar as opções -Le -He ver se isso seria suficiente a sua exigência.

Sree
fonte
legal, aprenda algo novo todos os dias.
rob
@Sree - Muito obrigado! Eu tentei as lsopções, mas não file. Infelizmente, nenhum dos dois parece funcionar :(
Chris Snow
@SHC Desculpe, eu assumi que você está em uma linuxcaixa. Adicione osxcomo uma de suas tags. Isso deve chamar a atenção dos osxusuários também. Editei a postagem para adicionar a tag, mas não tenho créditos suficientes para que a edição apareça imediatamente.
Sree
@Ree - não se preocupe, e desculpe pela confusão. Eu votei sua resposta de qualquer maneira, pois será útil quando eu estiver de volta em uma máquina Linux.
Chris Neve
talvez verifique o utilitário 'readlink' no osx.
tonioc
2

Com um GNU lspelo menos (e, aparentemente, tcsha implementação), você pode hackear a $LS_COLORSvariável de ambiente para inserir delimitadores onde quiser (mas tcsho built-in ls-Fnão faz destinos de link - apenas sinalizadores de link ) Normalmente lsinsere escapes arbitrários e imprimíveis do terminal com base nos valores armazenados nesse ambiente var, mas não há nada que nos impeça de inserir algo arbitrário. Mais sobre isso aqui .

Por exemplo:

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

Isso coloca uma string como //no início de todas as listagens (logo antes lrwcrwx) e a ///\nlogo antes do nome do arquivo de qualquer link. sedem seguida, filtra os intervalos de linhas - ele dexclui todas as linhas de entrada até encontrar ///e a partir daí, até a próxima linha correspondente //, excluirá as linhas correspondentes //. Portanto, ele obtém apenas o nome e o destino do link - independentemente dos caracteres intervenientes. Isso ocorre porque /não pode ocorrer em um nome de arquivo - e aqueles em qualquer caminho que lspodem ser impressos ocorrerão apenas individualmente.

Vejo?

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'

... que imprime:

long


name.ln -> long


name
shortname.ln -> shortname

Tente você mesmo.

mikeserv
fonte
Você conhece alguma implementação além das versões modernas do GNU lsque suporta LS_COLORSessa maneira e a --color=alwayse options após argumentos? Se em um sistema GNU, por que você usaria algo complicado quando você pode usar findou stat? Isso também provavelmente não funcionará se você fizer alguma ln -s /// some-file.
Stéphane Chazelas
@StephaneChezales - isso indica pelo menos que ele deve funcionar de forma semelhante com a BSD ls. Lembro-me de ler isso em algum outro lugar meses atrás, sobre lstudo tendendo a aceitar um termo como sintaxe. Bom argumento sobre o ln -s ///assunto - mas os \0NULs também funcionam - e -Recursivamente. Quanto ao porquê - bem, é fácil de usar. Em alguns casos, mais fácil do que find- e parecia um pouco mais sobre o assunto aqui do que findteria sido. De qualquer forma, poucas pessoas consideram isso, então eu menciono quando sou lembrado.
mikeserv
Consulte a página man ou não para o FreeBSD. Se você quiser testar coisas no FreeBSD, poderá usar CDs ao vivo como o GhostBSD / mfsbsd em uma VM.
Stéphane Chazelas
@ StéphaneChazelas - não, eu não preciso testá-lo - definitivamente um animal totalmente diferente . Se você deseja procurar, a fonte gnu também está vinculada no link nesta resposta. Gostaria de saber onde eu li essa outra coisa? muito obrigado por apontar isso, porém, essa foi uma suposição equivocada que estou feliz em descartar. Eu editei a resposta.
mikeserv
as versões recentes de tcshpossuem um ls-Fbuilt-in que suporta LS_COLORSda mesma maneira que algumas versões do GNU ls, mas ele recorre ls -Fse você passar alguma opção para ele, para que não funcione aqui, a menos que lsesteja o GNU lsno seu sistema.
Stéphane Chazelas 12/12
-1

[No Linux / Bash]

Eu faria o seguinte:

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

O sedcomando recolhe vários espaços em um único espaço; a cutextrai do campo 9 para a frente, onde o campo é um separador de espaço.

Saída típica disso:

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

As alternativas são:

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

Mas esses são imperfeitos: o primeiro pode gerar espaços à direita; o segundo, espaços principais.

Rhubbarb
fonte
A pergunta dizia explicitamente "... sem ter que passar por outro comando ..."
Jeff Schaller
@ JeffSchaller: Bom ponto; Concordo. Espero, no entanto, que isso ainda seja útil para alguém que queira uma resposta para a pergunta do título (sem os detalhes na descrição).
21715 Rhubbarb