encuentra todos los enlaces simbólicos en un árbol de directorios que apuntan fuera de ese árbol

8

Frecuentemente muevo árboles de directorios a otras ubicaciones o copie sus tarballs a otras máquinas, y me gustaría tener un método para verificar si algún enlace simbólico en un árbol de directorios A apunta a ubicaciones fuera de A ya que estos se romperán en el movido / copiado directorio.

Marcus Junius Brutus
fuente

Respuestas:

7

Desea que se llame un programa realpath, que se usa junto con find.

P.ej:

find . -type l -exec realpath {} \; | grep -v "^$(pwd)"
bahamat
fuente
1
El encantamiento que proporciona solo informa la ubicación del objetivo ofensivo, no el enlace simbólico que apunta a él. Como tal, he eliminado mi aceptación. Consulte mi "respuesta" a continuación: unix.stackexchange.com/a/308899/24044 y, si está satisfecho (o lo mejora), eliminaré mi "respuesta" y aceptaré su pregunta nuevamente.
Marcus Junius Brutus
2

Use bindfs para crear otra vista de ese árbol de directorios.

mkdir /tmp/view
bindfs /some/directory /tmp/view

Luego use la utilidad de enlaces simbólicos (enviada por muchas distribuciones, o compílela desde la fuente ) para detectar enlaces entre sistemas de archivos.

symlinks -r /tmp/view | sed -n 's/^\(absolute\|other_fs\): //p'

(Tenga en cuenta que al analizar la salida se supone que sus enlaces simbólicos y sus objetivos no contienen nuevas líneas, ni las rutas a los enlaces simbólicos contienen la subcadena  -> ). Esa misma utilidad también puede convertir enlaces simbólicos absolutos a relativos (pero querrá hacerlo desde La ubicación original).

Gilles 'SO- deja de ser malvado'
fuente
2

Con zsh:

cd -P -- "$dir"
for i (**/*(ND@)) [[ $i:A = $PWD/* ]] || [[ $i:A = $PWD ]] || print -r -- "$i => $i:A"

Ahora, si el directorio es /fooy tiene /foo/barun enlace simbólico /foo/baz, ese es un enlace cuyo objetivo está en / foo, pero una vez movido, el enlace seguirá roto, por lo que es posible que también desee hacer coincidir los enlaces simbólicos con las rutas absolutas.

Pero incluso entonces, una bar => ../foo/bazen /foosería un problema (falso negativo), por lo que sería una a => bdonde bes un enlace simbólico fuera del árbol (falsos positivos, dependiendo de cómo desea que mirarlo)

Stéphane Chazelas
fuente
2

Tuve que ajustar un poco la respuesta dada por @bahamat para que funcione.

La versión proporcionada simplemente informó la ubicación absoluta ofensiva, pero no el enlace simbólico que apunta a ella.

Esto es lo que usé (estoy seguro de que se puede mejorar):

for f in $(find . -type l ); do echo -n $(realpath $f) && echo -n "|" && echo $f ; done | grep -v "^$(pwd)" | cut -d \| -f 2 
Marcus Junius Brutus
fuente
Encontré que este es el script más útil: for f in $(find . -type l); do echo $(realpath -m -q $f) '<-' $f; done | grep-v "^$(pwd)"(más notablemente -my -qque filtra los enlaces rotos y no externos)
Adam Lindberg
1

GNU coreutils provedes realpath, que resuelve enlaces simbólicos. Con esto, puede comparar el objetivo de cada enlace simbólico con el directorio de trabajo actual con algo como:

#!/bin/bash

find . | while read filename
do
  if realpath $filename | grep -E "^$PWD" > /dev/null
  then
    echo 'this file is safe'
  else
    echo 'this file links externally'
  fi
done
dos puntos
fuente
Varios problemas: no -type l, ninguna -ropción para read, IFS no desinfectado read, $filenameno citado, $PWDtratado como una expresión regular, las rutas con caracteres de nueva línea no contabilizados, /foobarserían igualadas $PWD== "/ foo"
Stéphane Chazelas