¿Cómo puedo editar enlaces simbólicos?

64

Mi comprensión básica de un enlace simbólico es como un archivo especial, un archivo que contiene una ruta de cadena a otro archivo. El VFS del núcleo extrae mucho de eso, pero ¿hay alguna razón por la cual los enlaces simbólicos parezcan imposibles de editar?

En otras palabras: ¿puedo editar un enlace simbólico? ¿Si no, porque no?


Entiendo que hay varias formas de reemplazar los enlaces simbólicos (actualmente hay dos alternativas en la sección de respuestas), pero sería interesante obtener una explicación de por qué el reemplazo parece ser la única forma de tratar los enlaces simbólicos. ¿Por qué no puedes simplemente cambiar dónde apuntan?

Oli
fuente
Tu comprensión es un poco limitada; la única razón por la que se llama 'archivo' es porque no hay mejor palabra para ello.
Shadur
55
A diferencia de la vergonzosa atrocidad que es la variante de Windows, los enlaces simbólicos de estilo posix operan en / en la capa del sistema de archivos. La única forma de editar uno sería editar el sistema de archivos directamente, y generalmente no vale la pena.
Shadur
Los archivos @Shadur .lnk no son realmente enlaces simbólicos para empezar (y NTFS ha tenido enlaces simbólicos adecuados desde Vista); son más como accesos directos para ejecutar comandos, ya sea que esté cambiando a una carpeta específica o iniciando un programa con argumentos específicos y con un cierto CWD.
JAB

Respuestas:

36

Dado que -fsolo hace un reemplazo silencioso, puede hacer un reemplazo atómico con mv -T(-T lo hace funcionar incluso si /loc.../link es un directorio) :

ln -s /location/to/link linkname
# ... 
ln -s /location/to/link2 newlink
mv -T newlink linkname

linkname Es accesible durante todo el proceso.

Oli
fuente
77
Eso le da el reemplazo atómico, aunque todavía está haciendo un reemplazo en lugar de editar (el nuevo enlace tiene un nuevo número de inodo).
psusi
2
@psusi Estoy completamente de acuerdo, es solo una opción técnicamente un poco mejor que la otra respuesta en algunos escenarios.
Oli
Si está redirigiendo el enlace a otro destino, cambiar su número de inodo parece un pequeño cambio.
enms.
44
Eso supone linknameque no es un enlace simbólico a un directorio. Use la -Topción mvif en GNU o -hen FreeBSD para evitar eso. Tenga en cuenta que así ln -sfno se conservan los permisos del enlace (en sistemas donde son significativos).
Stéphane Chazelas
Otra solución para el cambio enlace simbólico para el directorio es el uso de -nlas opciones, por ejemplo: ln -sfn DESTINATION_DIRECTORY LINK_NAME. Más información en askubuntu.com/a/186227/69004
sobi3ch
22

Si por edición, quiere cambiar el archivo al que apunta, entonces sí puede:

$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 8 2009-09-23 17:12 test -> .profile

El -fparámetro ( --force) cuando se pasa a ln hace que llame a la llamada del unlink()sistema justo antessymlink()

Tomado de la siguiente respuesta de desbordamiento de pila .

NlightNFotis
fuente
99
Creo que es cuestionable si esto puede considerarse como "editar", ya que unlink (); symlink (); no es atómico, por lo que hay una pequeña cantidad de tiempo durante el cual el enlace no existe.
reproducir el
@ mauro.stettler Sí, tienes razón. Pero supongo que esto depende de tu perspectiva. Si solo tiene en cuenta el resultado final, entonces tal vez podría considerarlo editado, sin considerar otras cosas.
NlightNFotis
1
La sección citada del documento del Sistema de tiempo compartido de Unix describe enlaces duros . Estos son completamente diferentes de los enlaces simbólicos (enlaces simbólicos) sobre los que el OP preguntó.
Ansgar Esztermann
44
Tenga en cuenta que supone que testel objetivo no es un directorio. De ln -s -f .profile testlo contrario , crearía un .profileenlace simbólico en ese directorio. GNU lntiene una -Topción para evitar eso.
Stéphane Chazelas
9

Los enlaces simbólicos deben modificarse atómicamente. Si estás a la mitad de escribirlas, no funcionarán. El contenido de un enlace simbólico es bastante pequeño (como máximo 4095 caracteres en Linux: la longitud máxima de una ruta a un archivo), por lo que no tendría mucho sentido editar parte de un enlace simbólico a nivel del núcleo. Por lo tanto, el núcleo no ofrece ninguna interfaz para editar un enlace simbólico, solo una interfaz para crear uno nuevo, la symlinkllamada al sistema (más la interfaz genérica unlinkpara eliminar cualquier archivo).

La symlinkllamada al sistema solo crea un nuevo enlace simbólico, no elimina ningún archivo existente. Esto es molesto, pero coherente con otras llamadas del sistema para crear archivos como open(que puede crear un nuevo archivo o truncar un archivo existente, pero no reemplazar un archivo existente por un archivo recién creado) y mkdir.

En el shell, como descubrió , aunque no puede reemplazar un enlace simbólico atómicamente con el lncomando ( ln -sfdesvincula el archivo anterior y luego crea el enlace simbólico), puede hacerlo creando primero un enlace simbólico con un nombre temporal y luego moviéndolo a su lugar.

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"
Gilles 'SO- deja de ser malvado'
fuente
2
mv -f(como ln -sf) no hará lo que quiera si $linkapunta a un directorio. GNU ln y mv tienen un -Tpara eso. mv(cambiar el nombre de la llamada al sistema) siempre cambiará el inodo de $linkwhile ln -sfT(unlink + symlink) podría reutilizar lo mismo.
Stéphane Chazelas
0

Técnicamente, no hay un comando incorporado para editar un enlace simbólico existente. Se puede lograr fácilmente con unos pocos comandos cortos.

Aquí hay una pequeña función bash / zsh que escribí para actualizar un enlace simbólico existente:

# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with 
# -----------------------------------------
function edit-symlink () {
    if [ -z "$1" ]; then
        echo "Name of symbolic link you would like to edit:"
        read LINK
    else
        LINK="$1"
    fi
    LINKTMP="$LINK-tmp"
    if [ -z "$2" ]; then
        echo "Full destination path to update existing symlink with:"
        read DEST
    else
        DEST="$2"
    fi
    ln -s $DEST $LINKTMP
    rm $LINK
    mv $LINKTMP $LINK
    printf "Updated $LINK to point to new destination -> $DEST"
}
blizzrdof77
fuente
Lo sentimos, pero su "respuesta" está solo remotamente relacionada con la pregunta que se le hizo.
user2233709
Hola @ user2233709: la pregunta del usuario " ¿Cómo puedo editar enlaces simbólicos? " Se respondió claramente en la primera oración, así como al proporcionar una solución. ¿Te gustaría elaborar?
blizzrdof77
2
¿Realmente leíste la pregunta? Se trata de si es posible modificar un enlace simbólico, en lugar de reemplazarlo . Su "solución" propuesta es un script que reemplaza un enlace simbólico.
user2233709
0

Suponga que linkname existe como resultado de haberlo hecho (en el pasado):

 ln -s   /the/path/to/a/file   linkname

Luego, hay tres formas de cambiar el enlace simbólico:

  • Use ln con -ffuerza e incluso para directorios -n(el inodo podría reutilizarse):

    ln -sfn /some/new/path linkname
    
  • Elimine el enlace simbólico y cree uno nuevo (incluso para directorios):

    rm linkname; ln -s /some/new/path linkname
    
  • cree un nuevo enlace simbólico, luego mv(cambio atómico incluso para directorios):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
Isaac
fuente