12 votos

¿Cómo encuentro enlaces simbólicos rotos en macOS?

Me gustaría aprender cómo encontrar enlaces simbólicos rotos, de forma recursiva dada una ruta.

Como una referencia precisa de lo que estoy buscando, el equivalente en Linux (que no funciona en macOS) sería find -xtype:

find /ruta/al/directorio -xtype l

13voto

siva Puntos 23
find /ruta/al/directorio -type l ! -exec [ -e {} ] \; -print

-exec ejecuta un comando para cada resultado.
[ -e … ] prueba si el destino existe.
! niega el resultado del exec (donde el destino no existe).
-print imprime los resultados.

4voto

staffan Puntos 3299

Con las herramientas que vienen con macOS, la forma más sencilla es usar zsh: sus glob qualifiers permiten filtrar por tipo de archivo. El glob qualifier @ es el análogo de -type l para el comando find, y el glob qualifier - es el análogo de usar -xtype en lugar de -type.

print -lr -- /ruta/hacia/directorio/**/*(-@)

También es de interés si vas a trabajar en enlaces simbólicos en zsh:

  • Ejecuta zmodload -F zsh/stat b:zstat para cargar el zstat integrado. Esto te permite imprimir el contenido de un enlace simbólico (el valor devuelto por readlink) con zstat +link -- $ruta_algun_lugar. Esto es lo mismo que readlink -- $ruta_algun_lugar, pero más rápido y te permite almacenar el resultado en una variable con zstat -A target +link -- $ruta_algun_lugar sin tener que preocuparte por casos especiales con objetivos que contienen saltos de línea.
  • ...(:A) aplica el history modifier A a un camino, que resuelve todos los enlaces simbólicos en el camino.

3voto

OrangeDog Puntos 101

No probado en macOS, pero esto debería funcionar, devolviendo todos los enlaces que no se pueden seguir:

find -L /ruta/al/directorio -type l -print

De lo contrario, esto encuentra todos los enlaces, y para cada uno ejecuta un comando de shell para verificar si el destino existe, y si no imprime la ruta:

find /ruta/al/directorio -type l -exec sh -c 'test -e {} || echo {}' \;

2voto

Aeronautix Puntos 31

Quiero dar una respuesta, basada en la respuesta de grg anterior, sobre cómo tomar todos los enlaces simbólicos rotos encontrados y transformarlos en una forma reutilizable en shell, de forma portátil en bash y zsh (primero ver los comentarios de David Anderson abajo y mi entrada editada en "${pathnames[@]:"$i":1}").

También quiero mencionar las dos siguientes equivalencias, funcionarán de la misma manera:

  • find ... ! -exec test -e {} \; significa si el nombre de ruta (resolviendo enlaces simbólicos) existe, no lo encuentres. "!" se usa aquí por "find". También se puede substituir "-not" en lugar de "!".
  • find ... -exec test ! -e {} \; significa si el nombre de ruta (resolviendo enlaces simbólicos) no existe, encuéntralo. "!" se usa aquí por "test". Usaré esto en el siguiente ejemplo.

Ejemplo para (1) almacenar, (2) imprimir, y (3) contar los enlaces simbólicos rotos

pathnames=()
while IFS= read -r -d $'\0' pathname; do
  pathnames+=( "$pathname" )
done < <(find . -type l -exec test ! -e {} \; -print0)

for (( i=0; i<${#pathnames[@]}; i++ )); do
  printf "%q\n" "${pathnames[@]:"$i":1}"
done

printf "\nEnlaces simbólicos rotos encontrados: %s\n" "${#pathnames[@]}"
  • pathnames es un arreglo para almacenar los nombres de ruta encontrados, en este caso enlaces simbólicos rotos.
  • find . -type l -exec test ! -e {} \; significa buscar en y debajo del directorio actual enlaces simbólicos rotos. -type l encuentra enlaces simbólicos y test ! -e prueba si el nombre de ruta resuelto del enlace simbólico no existe.
  • -print0 significa delimitar los nombres de ruta encontrados de find usando bytes NUL, e imprimirlos.
  • < <(...) significa la sustitución de procesos en bash/zsh y redirigir en stdin de read.
  • while ... read significa ejecutar read hasta que encuentre el final del archivo o experimente un error.
  • IFS= significa no truncar espacios en blanco al final o al inicio de la ruta.
  • -r significa no permitir que las barras invertidas escapen de los caracteres; no interpretar las barras invertidas.
  • -d $'\0', o -d '', significa leer la entrada delimitada por bytes NUL.
  • printf "%q\n" aprovecha la función integrada printf de bash/zsh para imprimir los nombres de ruta en una forma reutilizable en shell.
  • "${pathnames[@]:"$i":1}" usa indexación de arreglos indexados en 0 en bash/zsh.
    • Como se señala abajo en los comentarios de David Anderson, cambiar "$i" a $i (sin las comillas) funcionará de manera más portátil y no hará que esta parte de código falle para versiones antiguas de bash/zsh, dado que $i no se expande en nada más que un índice entero. Quiero señalar que es un error en las versiones antiguas no poder incluir comillas para prevenir expansiones no deseadas dentro de expansiones de parámetros similares a arreglos.
    • Probé mi código en bash v5.2.26(1) y zsh v5.9, pero olvidé probar en bash v3.2.57(1), que es la versión de bash* muy antigua que Apple aún conserva en Macs* (normalmente pruebo esta versión de bash con el código que tengo) (*también ver gran información sobre la versión de bash de Apple y sobre los Macs relacionados en la sección de comentarios abajo por David Anderson). "${pathnames[@]:"$i":1}" fallará en esta versión antigua de bash, y también fallará en zsh 5.7.1 según se señala abajo por David Anderson.
    • En resumen, para una indexación portable, usa "${pathnames[@]:$i:1}" en su lugar.

Más información sobre el loop while ... read: https://mywiki.wooledge.org/BashFAQ/001

Configuración de muestra

Crea algunos enlaces simbólicos rotos y enlaces simbólicos de directorio rotos con algunas nuevas líneas y retornos de carro:

ln -s nofile 'enlace simbólico roto'
ln -s nofile $'enlace simbólico roto\ncon\nnuevas líneas'
ln -s nofile $'enlace simbólico roto con\r retorno de carro'
mkdir tempdir
ln -s tempdir 'enlace de directorio roto'
ln -s tempdir $'enlace\r de \r directorio\r rotos'
sleep 1; rm -d tempdir
  • sleep 1 se utiliza para que Finder pueda ponerse al día mostrando los íconos de los enlaces simbólicos de carpeta para los dos directorios de enlaces simbólicos rotos.

Salida en zsh, y luego en bash

./enlace\ simbólico\ roto
./enlace\ simbólico\ roto\ con$'\r'\ retorno\ de\ carro
./enlace\ $'\r'\ de\ $'\n'_rotos
./enlace\ de\ directorio\ roto
./enlace\ simbólico$'\n'con$'\n'nuevas líneas

Enlaces simbólicos rotos encontrados: 5

./enlace\ simbólico\ roto
$'./enlace simbólico roto con\r retorno de carro'
$'./enlace \r de \n_rotos'
./enlace\ de\ directorio\ roto
$'./enlace simbólico\ncon\nnuevas líneas'

Enlaces simbólicos rotos encontrados: 5

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X