Tengo una completa sub-sistema de archivos dentro de un trazado /home/user/system
que 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/file1
que ahora apunta a un archivo /usr/lib/file1
fuera 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
symlinks
utilidad de Mark Lord (ofrecida por muchas distribuciones; si la suya no la tiene, compílela desde la fuente ):Alternativamente, en sistemas que tienen un
readlink
comando y un-lname
predicado parafind
(advertencia: código no probado):fuente
_ {} +
al final del hallazgo? Además,find: paths must precede expression: ksh
aparece un error que no parece tener sentido (ya que la ruta precede a la expresión ksh)._
es$0
para 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 defind
se 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/directory
convertir enlaces simbólicos en ese directorioln -fs
aecho ln -fs
un 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
if
clá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 -f
sobrescribe 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