unix - simbolica - enlace simbolico windows
¿Puedes cambiar a qué apunta un enlace simbólico después de que se crea? (7)
¿Algún sistema operativo proporciona un mecanismo (llamada al sistema, no programa de línea de comandos) para cambiar el nombre de ruta referenciado por un enlace simbólico (enlace simbólico), aparte de desvincular el antiguo y crear uno nuevo?
El estándar POSIX no. Solaris 10 no. MacOS X 10.5 (Leopard) no. (Estoy bastante seguro de que ni AIX ni HP-UX lo hacen. A juzgar por esta lista de llamadas al sistema Linux, Linux tampoco tiene esa llamada al sistema).
¿Hay algo que haga?
(Estoy esperando que la respuesta sea "No").
Dado que probar un negativo es difícil, reorganicemos la pregunta.
Si sabe que algún sistema operativo (similar a Unix) que no se encuentra en la lista no tiene una llamada al sistema para reescribir el valor de un enlace simbólico (la cadena devuelta por readlink()
) sin eliminar el enlace simbólico antiguo y crear uno nuevo, agréguelo - o ellos - en una respuesta.
¡Sí tu puedes!
$ ln -sfn source_file_or_directory_name softlink_name
¿No sería desvinculándolo y creando el nuevo hacer lo mismo al final de todos modos?
En caso de que ayude: hay una manera de editar un enlace simbólico con el comandante de medianoche (mc). El comando de menú es (en francés en mi interfaz mc):
Fichier / Éditer le lien symbolique
que puede traducirse a:
File / Edit symbolic link
El atajo es Cx Cs
Quizás internamente usa el comando ln --force
, no lo sé.
Ahora, estoy tratando de encontrar una manera de editar una gran cantidad de enlaces simbólicos a la vez (así es como llegué aquí).
No es necesario desvincular explícitamente el enlace simbólico antiguo. Puedes hacerlo:
ln -s newtarget temp
mv temp mylink
(o usa el enlace simbólico equivalente y renombra las llamadas). Esto es mejor que desvincularse explícitamente porque el cambio de nombre es atómico, por lo que puede estar seguro de que el enlace siempre apuntará al objetivo anterior o al nuevo. Sin embargo, esto no reutilizará el inodo original.
En algunos sistemas de archivos, el objetivo del enlace simbólico se almacena en el inodo mismo (en lugar de la lista de bloqueo) si es lo suficientemente corto; esto se determina en el momento en que se crea.
Con respecto a la afirmación de que el propietario y el grupo reales son inmateriales, el symlink(7) en Linux dice que hay un caso en el que es significativo:
El propietario y el grupo de un enlace simbólico existente se pueden cambiar usando lchown (2). El único momento en que importa la propiedad de un enlace simbólico es cuando el enlace se elimina o se renombra en un directorio que tiene el bit adhesivo establecido (ver stat (2)).
Las últimas marcas de tiempo de acceso y última modificación de un enlace simbólico se pueden cambiar usando utimensat (2) o lutimes (3).
En Linux, los permisos de un enlace simbólico no se usan en ninguna operación; los permisos son siempre 0777 (lectura, escritura y ejecución para todas las categorías de usuarios) y no pueden modificarse.
Solo una advertencia a las respuestas correctas anteriores:
El uso del método -f / --force proporciona un riesgo de perder el archivo si mezcla el origen y el destino:
mbucher@server2:~/test$ ls -la
total 11448
drwxr-xr-x 2 mbucher www-data 4096 May 25 15:27 .
drwxr-xr-x 18 mbucher www-data 4096 May 25 15:13 ..
-rw-r--r-- 1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
-rw-r--r-- 1 mbucher www-data 7582480 May 25 15:27 otherdata.tar.gz
lrwxrwxrwx 1 mbucher www-data 11 May 25 15:26 thesymlink -> data.tar.gz
mbucher@server2:~/test$
mbucher@server2:~/test$ ln -s -f thesymlink otherdata.tar.gz
mbucher@server2:~/test$
mbucher@server2:~/test$ ls -la
total 4028
drwxr-xr-x 2 mbucher www-data 4096 May 25 15:28 .
drwxr-xr-x 18 mbucher www-data 4096 May 25 15:13 ..
-rw-r--r-- 1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
lrwxrwxrwx 1 mbucher www-data 10 May 25 15:28 otherdata.tar.gz -> thesymlink
lrwxrwxrwx 1 mbucher www-data 11 May 25 15:26 thesymlink -> data.tar.gz
Por supuesto, esto es así, pero generalmente ocurren errores. Por lo tanto, eliminar y reconstruir el enlace simbólico es un poco más laborioso pero también un ahorro de bits:
mbucher@server2:~/test$ rm thesymlink && ln -s thesymlink otherdata.tar.gz
ln: creating symbolic link `otherdata.tar.gz'': File exists
que al menos mantiene mi archivo.
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"
}
AFAIK, no, no puedes. Tienes que eliminarlo y recrearlo. En realidad, puede sobreescribir un enlace simbólico y así actualizar la ruta a la que hace referencia:
$ 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
EDITAR : Como el OP señaló en un comentario, usar la opción --force
hará que ln
realice una llamada al sistema para unlink()
antes de symlink()
. A continuación, la salida de strace
en mi linux box lo demuestra:
$ strace -o /tmp/output.txt ln -s -f .bash_aliases test
$ grep -C3 ^unlink /tmp/output.txt
lstat64("test", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0
stat64(".bash_aliases", {st_mode=S_IFREG|0644, st_size=2043, ...}) = 0
symlink(".bash_aliases", "test") = -1 EEXIST (File exists)
unlink("test") = 0
symlink(".bash_aliases", "test") = 0
close(0) = 0
close(1) = 0
Así que supongo que la respuesta final es "no".
EDITAR : Lo siguiente se copia de la respuesta de Arto Bendiken en unix.stackexchange.com, alrededor del año 2016.
Esto se puede hacer atómicamente con rename(2)
, creando primero el nuevo enlace simbólico bajo un nombre temporal y luego sobrescribiendo limpiamente el viejo enlace simbólico de una vez. Como dice la página del manual :
Si newpath se refiere a un enlace simbólico, el enlace se sobrescribirá.
En el shell, harías esto con mv -T
siguiente manera:
$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z
Puedes strace
ese último comando para asegurarte de que está usando el rename(2)
debajo del capó:
$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z") = 0
Tenga en cuenta que en lo anterior, tanto mv -T
y strace
son específicos de Linux.
En FreeBSD, use mv -h
alternativamente.
Nota del editor: Así es como Capistrano lo ha hecho durante años, desde ~ 2.15. Ver esta solicitud de extracción .