¿Cómo editar recursivamente la ruta de los enlaces simbólicos?

4

Esta es una pregunta adicional que comenzó con esta: ¿Cómo editar enlaces simbólicos en OS X?

Ahora que sé cómo editar la ruta a la que apuntan los enlaces simbólicos, estoy tratando de averiguar cómo hacer esto recursivamente para cualquier enlace simbólico roto. Soy un tipo de PHP, por lo que este tema de CLI es un tanto extraño para mí ...

Parece que hay algunos elementos específicos para esto, a saber:

  1. Identifique un enlace simbólico roto y recupere su ubicación
  2. Obtenga el destino antiguo, ahora incorrecto, para el enlace simbólico
  3. Construya la nueva ruta correcta para que el enlace simbólico apunte a
  4. Editar el enlace simbólico

El primero es bastante fácil:

find /path/to/search -type l | while read f; do if [ ! -e "$f" ]; then ls -l "$f"; fi; done

Esto me proporciona una buena lista de todos los enlaces simbólicos rotos que se encuentran debajo del directorio provisto. Pero creo que necesitaría almacenar la ubicación de cada uno en una variable (¿matriz?) Para trabajar con ella.

A continuación, parece que cambiar la acción suministrada en la parte "entonces" de la lógica daría la solución.

El elemento 2 se puede recuperar usando:

readlink /path/to/broken/symlink

Parece que tenemos que meter eso en una variable. No tengo claro cómo hacer esto en la terminal.

El número 3 sería una simple edición de la ruta recuperada durante el paso 2. Necesito reemplazar el nombre de la unidad anterior con el nuevo. Tan cambiante:

/Volumes/Old\ Drive/path/to/symlink

a

/Volumes/New\ Drive/path/to/symlink

Tampoco está claro exactamente cómo hacerlo dentro de un script de CLI. Parece que se necesita algún tipo de reemplazo de cadena. Algo así como str_replace en el mundo de PHP.

Finalmente, el paso 4 se puede hacer a través de:

ln -f -s /path/to/new/location/of/original /path/to/location/of/broken/symlink/

como se detalla en mi otra pregunta, anteriormente vinculada.

¿Cómo exactamente uniré estos conceptos para lograr el resultado deseado al arreglar todos mis enlaces simbólicos de una sola vez?

    
pregunta Jonathan van Clute 08.12.2013 - 08:33

2 respuestas

5

Desde la parte superior de mi cabeza (y sin ninguna prueba):

  1. Crea un archivo de texto con el siguiente contenido

    #!/bin/bash
    
    find "$1" -type l | while read symlink; do
        if [ ! -e "$symlink" ]; then
            old_path=$(readlink "$symlink")
            new_path=${old_path/Old Drive/New Drive}
            ln -f -s "$new_path" "$symlink"
        fi
    done
    
  2. Hazlo ejecutable ejecutando chmod +x name-of-file

  3. Ejecutar ./name-of-file /path/to/search

Esto es no probado así que inténtalo con un directorio de muestra primero.

Para agregar algunas explicaciones

  • old_path=$(readlink "$symlink") ejecuta el comando en $(...) y asigna el resultado a $old_path
  • ${old_path/Old Drive/New Drive} hace sustitución de texto en $old_path
respondido por el nohillside 08.12.2013 - 11:12
5

En un shell bash , para establecer una variable, simplemente usa set NAME=bob o set VITAL_SIGNS=none .

También puede establecer una variable utilizando la salida de un comando llamando a la función bash -builtin read para asignar la salida a una variable nombrada. Esto funciona bien en un flujo de tubería como tal:

ls -l | wc -l | read NUMBER_OF_LINES

O puede asignar la salida directamente a una variable de la siguiente manera:

LICENSE_KEY=$(cat ~/software/key.txt | grep KEY | awk '{print $1}')

Una excelente manera de leer las variables de forma recursiva es en un bucle de la siguiente manera:

for BROKEN_LINK in $(commands to produce a list of files)
do
commands here to sort your links out, noting that the broken links are stored in the variable $BROKEN_LINKS
done

Con lo anterior en mente, algo como lo siguiente debería funcionar:

compruebe que una carpeta no existe

StuffeMac:dan stuffe$ ls ~/Desktop/broken_links
ls: /Users/stuffe/Desktop/broken_links: No such file or directory

compruebe que existe una nueva carpeta de destino

StuffeMac:dan stuffe$ ls ~/Desktop/working_links
StuffeMac:dan stuffe$

crea algunos enlaces inválidos y válidos

StuffeMac:dan stuffe$ ln -s ~/Desktop/brokenlinks/dan1
StuffeMac:dan stuffe$ ln -s ~/Desktop/brokenlinks/dan2
StuffeMac:dan stuffe$ ln -s ~/Desktop/working_links/dan3
StuffeMac:dan stuffe$ ln -s ~/Desktop/outofscopedeadlinks/dan4
StuffeMac:dan stuffe$ ls -l
total 32
lrwxr-xr-x  1 stuffe  staff  38  8 Dec 10:06 dan1 -> /Users/stuffe/Desktop/brokenlinks/dan1
lrwxr-xr-x  1 stuffe  staff  38  8 Dec 10:06 dan2 -> /Users/stuffe/Desktop/brokenlinks/dan2
lrwxr-xr-x  1 stuffe  staff  40  8 Dec 10:06 dan3 -> /Users/stuffe/Desktop/working_links/dan3
lrwxr-xr-x  1 stuffe  staff  46  8 Dec 10:21 dan4 -> /Users/stuffe/Desktop/outofscopedeadlinks/dan4

agarra una lista de enlaces muertos en un archivo para su entrada

StuffeMac:dan stuffe$ find . -type l | while read f; do if [ ! -e "$f" ]; then ls "$f" >> deadlinks.txt; fi; done
StuffeMac:dan stuffe$ more deadlinks.txt
./dan1
./dan2
./dan4

ejecuta un bucle contra cada enlace muerto

StuffeMac:dan stuffe$ for DEAD_LINK in $(cat deadlinks.txt)
> do
> DESTINATION_IN_SCOPE=$(readlink $DEAD_LINK | grep brokenlinks | wc -l)
> NEW_DESTINATION="~/Desktop/working_links/"
> if [ $DESTINATION_IN_SCOPE = "1" ]
> then
> NEW_LINK=$(echo $DEAD_LINK | colrm 1 2)
> ln -f -s $NEW_DESTINATION$NEW_LINK $DEAD_LINK
> else
> echo "Link $DEAD_LINK not in target folder"
> fi
> done
Link ./dan4 not in target folder
StuffeMac:dan stuffe$

revisa los enlaces simbólicos después de las ediciones

StuffeMac:dan stuffe$ ls -l
total 32
lrwxr-xr-x  1 stuffe  staff  28  8 Dec 10:08 dan1 -> ~/Desktop/working_links/dan1
lrwxr-xr-x  1 stuffe  staff  28  8 Dec 10:08 dan2 -> ~/Desktop/working_links/dan2
lrwxr-xr-x  1 stuffe  staff  40  8 Dec 10:06 dan3 -> /Users/stuffe/Desktop/working_links/dan3
lrwxr-xr-x  1 stuffe  staff  46  8 Dec 10:21 dan4 -> /Users/stuffe/Desktop/outofscopedeadlinks/dan4
    
respondido por el stuffe 08.12.2013 - 11:16

Lea otras preguntas en las etiquetas