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