solo muestra el archivo fuente y el archivo vinculado de destino usando `ls`

11

Puedo mostrar el archivo de destino al que apunta un enlace 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

¿Hay alguna manera de mostrar menos salida sin tener que canalizar a través de otro comando como awk? P.ej:

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

Estoy ejecutando 3.2.53 en OS X 10.9.5. La salida de varios comandos se muestra a continuación:

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
fuente

Respuestas:

7

lsdesafortunadamente no tiene una opción para recuperar los atributos del archivo y mostrarlos de manera arbitraria. Algunos sistemas tienen comandos separados para eso (por ejemplo, GNU tiene un statcomando o la funcionalidad en GNU find).

Sin embargo, en la mayoría de los sistemas modernos, con la mayoría de los archivos, esto debería 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

Eso funciona eliminando los primeros 8 campos delimitados en blanco de la primera línea de la salida de ls -l. Eso debería funcionar, excepto en sistemas donde el gid no se muestra allí o los 2 primeros campos se unen cuando hay una gran cantidad de enlaces.

Con GNU stat:

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

Con GNU find:

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

Con estadísticas FreeBSD / OS / X:

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

Con zshstat:

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

Muchos sistemas también tienen un readlinkcomando para obtener específicamente el objetivo de un enlace:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi
Stéphane Chazelas
fuente
stat -f "%N -> %Y" -- /usr/local/bin/mvnfuncionó muy bien ¡Gracias!
Chris Snow
1
En un viejo sistema RHEL6, stat es de GNU coreutils 8.4 y ahí está a stat -c %N -- /usr/local/bin/mvn. Para eliminar las citas tuve que canalizar esto| perl -pe 's/['"'"'`]//g'
cfi
@cfi tr -d \'\`sería suficiente. Tenga en cuenta que ese sistema RHEL tendría GNU findcon el que tendrá más control.
Stéphane Chazelas
5

Usa el 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'

o

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

También, por favor ir a leer a través de la página de hombre lsy comprobar las opciones -Ly -Hver si eso sería suficiente su requisito.

Sree
fuente
genial, aprende algo nuevo todos los días.
robar
@Sree - ¡Muchas gracias! Había probado las lsopciones, pero no file. Desafortunadamente, ninguno parece funcionar :(
Chris Snow
@SHC Lo siento, asumí que estás en una linuxcaja. Agregue osxcomo una de sus etiquetas. Eso también debería llamar la atención de los osxusuarios. He editado la publicación para agregar la etiqueta, pero no tengo suficientes créditos para que la edición aparezca de inmediato.
Sree
@Sree: no te preocupes y perdón por la confusión. He votado tu respuesta de todos modos, ya que será útil cuando regrese a una máquina Linux.
Chris Snow
tal vez verifique la utilidad 'readlink' en osx.
tonioc
2

lsAl menos con un GNU (y, aparentemente, tcshla implementación de) , puede hackear la $LS_COLORSvariable de entorno para insertar delimitadores donde desee (pero tcshel incorporado ls-Fno hace objetivos de enlace, solo indicadores de enlace ) Por lo general lsinserta escapes de terminal arbitrarios no imprimibles basado en los valores almacenados dentro de ese entorno var, pero no hay nada que nos impida insertar algo arbitrario en su lugar. Más sobre esto aquí .

Por ejemplo:

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

Eso coloca una cadena como //el encabezado de cada lista (justo antes lrwcrwx) y ///\njusto antes del nombre de archivo de cualquier enlace. sedluego filtra en los rangos de línea: delegirá cada línea de entrada hasta que encuentre ///y, a partir de ahí, a través de la siguiente línea que coincida //, eliminará las líneas que coincidan //. Por lo tanto, solo obtiene el nombre y el destino del enlace, independientemente de los caracteres que intervienen. Esto se debe a /que no puede aparecer en un nombre de archivo, y aquellos en cualquier ruta lspueden imprimir solo ocurrirán individualmente.

¿Ver?

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

Inténtalo tú mismo.

mikeserv
fuente
¿Conoces alguna implementación además de las versiones modernas de GNU lsque admita LS_COLORSesa forma --color=alwaysy las opciones y después de los argumentos? Si está en un sistema GNU, ¿por qué usaría algo complicado si puede usar findo stat? Eso probablemente tampoco funcionará si haces algo ln -s /// some-file.
Stéphane Chazelas
@StephaneChezales: esto indica al menos que debería funcionar de manera similar con un bsd ls. Recuerdo haber leído eso en otro lugar hace meses acerca de que lstodos tienden a aceptar un término como la sintaxis. Un buen punto sobre el ln -s ///asunto, pero las \0NUL también funcionan, y de forma -Recursiva. En cuanto a por qué, bueno, es fácil de usar. En algunos casos es más fácil que find, y parecía un poco más sobre el tema aquí de findlo que hubiera sido. En cualquier caso, no muchas personas lo consideran, así que lo menciono cuando se me recuerda.
mikeserv
Vea la página del manual o allí para FreeBSD. Si desea probar cosas en FreeBSD, puede usar CD en vivo como GhostBSD / mfsbsd en una máquina virtual.
Stéphane Chazelas
@ StéphaneChazelas - no, no necesito probarlo - definitivamente es un animal completamente diferente . Si te interesa mirar, la fuente gnu también está vinculada en el enlace de esta respuesta. Me pregunto dónde leí esa otra cosa. muchas gracias por señalar eso, sin embargo, esa fue una suposición equivocada que estoy feliz de descartar. He editado la respuesta.
mikeserv
Las versiones recientes de tcshtienen una versión ls-Fincorporada que admite de LS_COLORSla misma manera que algunas versiones de GNU ls, pero recurre a la invocación ls -Fsi le pasa alguna opción, por lo que no funcionará aquí a menos que lssea ​​GNU lsen su sistema.
Stéphane Chazelas
-1

[En Linux / Bash]

Yo haría esto:

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

El sedcomando contrae múltiples espacios en un solo espacio; la cutextrae el campo noveno en adelante donde el campo-separador es un espacio.

Salida típica de esto:

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

Las alternativas son:

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

Pero esos son imperfectos: el primero puede generar espacios finales; el segundo, espacios principales.

Ruibarbo
fuente
La pregunta decía explícitamente "... sin tener que pasar por otro comando ..."
Jeff Schaller
@JeffSchaller: Buen punto; Estoy de acuerdo. Sin embargo, espero que esto siga siendo útil para alguien que quiera una respuesta a la pregunta del título (sin los detalles en la descripción).
Ruibarbo