Tengo una completa sub-sistema de archivos dentro de un trazado /home/user/systemque contiene la estructura estándar de Linux con los directorios /bin, /home, /root, /usr, /var, /etc, ...
Este subsistema de archivos contiene enlaces simbólicos, relativos o absolutos. Los enlaces simbólicos relativos están bien, permanecen dentro del subsistema de archivos debajo /home/user/system. Pero los enlaces simbólicos absolutos son problemáticos, ya que apuntan a un objetivo fuera del subsistema de archivos.
Como ejemplo, asumimos un enlace simbólico absoluto de la siguiente manera (visto dentro del subsistema de archivos):
/usr/file1 -> /usr/lib/file1
En el sistema de archivos general, tenemos un enlace /home/user/system/usr/file1que ahora apunta a un archivo /usr/lib/file1fuera del subsistema de archivos, en lugar de un archivo /home/user/system/usr/lib/file1 dentro del subsistema de archivos.
Me gustaría tener un script simple, preferiblemente una sola línea de comando (rsync, chroot, find, ...) que convierta cada enlace simbólico absoluto en uno relativo.
En el ejemplo dado, ese enlace relativo se convertiría en
/usr/file1 -> ../usr/lib/file1
fuente

Respuestas:
Con la
symlinksutilidad de Mark Lord (ofrecida por muchas distribuciones; si la suya no la tiene, compílela desde la fuente ):Alternativamente, en sistemas que tienen un
readlinkcomando y un-lnamepredicado parafind(advertencia: código no probado):fuente
_ {} +al final del hallazgo? Además,find: paths must precede expression: kshaparece un error que no parece tener sentido (ya que la ruta precede a la expresión ksh)._es$0para el fragmento de cáscara, y{} +se sustituye por la lista de argumentos que se convierten$1,$2, etc., quefor link; do …los bucles sobre (que es sinónimo defor link in "$@"; do …). El error defindse debe a un error tipográfico (de alguna manera logré escribir comillas inversas en lugar de comillas simples alrededor del argumento-lname).symlinks? Solucionaría su problema: para eso fue básicamente para lo que fue diseñado (con la molestia de que tiene que ejecutarlo chrooteado ( fakechroot debería ser el truco)).Pure bash & coreutils, cambia los enlaces simbólicos a relativos sin
../s innecesarios en la ruta:Tu puedes cambiar:
find .parafind /path/to/directoryconvertir enlaces simbólicos en ese directorioln -fsaecho ln -fsun simulacroExplicación:
target="$(realpath "$l")"- encuentra la ruta absoluta al objetivo del enlace simbólicoln -fs- crea symlink (-s), forzando (-f) reescribir de existenterealpath -s "$l"- encuentra la ruta absoluta al enlace simbólicodirname "$(realpath -s "$l")"- encuentra la ruta absoluta al directorio que contiene el enlace simbólicorealpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target"- encuentra la ruta del objetivo en relación con el enlace simbólico, en otras palabras: convierte la ruta absoluta en relativafuente
ifcláusula para omitir los enlaces rotos.Este fragmento de bash debería hacerlo. El primer formulario imprimirá lo que haría; el segundo lo hará. Revisaría cuidadosamente el resultado, ya que es destructivo:
ln -fsobrescribe el enlace existente.fuente
Aquí hay una solución sh pura.
fuente
La transformación absoluta en enlaces relativos es compatible con sshfs, que monta directorios remotos a través de ssh.
El comando es: hay
El comando, especialmente el
<placeholders>, se adaptará al entorno específico.fuente