suave - ln linux
¿Cómo convertir un enlace simbólico a un archivo normal? (14)
En OSX
rsync `readlink bar.pdf` bar.pdf
¿Cuál es la forma más directa de convertir un enlace simbólico en un archivo regular (es decir, una copia del objetivo del enlace simbólico)?
Supongamos que el filename
es un enlace simbólico al target
. El procedimiento obvio para convertirlo en una copia es:
cp filename filename-backup
rm filename
mv filename-backup filename
¿Hay una forma más directa (es decir, un solo comando)?
Esta solución funciona con archivos de enlaces simbólicos y carpetas / subcarpetas de enlaces simbólicos.
Una línea, no se necesita script. Esto sería ideal para exportar o transferir enlaces simbólicos a otros lugares.
Pon todo dentro de una carpeta.
rsync --archive --copy-links - carpeta recursivaContainingSymlinkFilesAndSymlinkFoldersAndSubfolders myNewFolder
Esto funcionó perfectamente para mí ( editado para trabajar con espacios ):
find . -type l | while read f; do /bin/cp -rf --remove-destination -f $(find . -name $(readlink "${f}")) "${f}";done;
Le permite convertir recursivamente todos los enlaces simbólicos de la carpeta de trabajo actual a su archivo normal. Tampoco te pide que sobreescribas. existe "/ bin / cp" para que pueda omitir un posible alias cp -i en su sistema operativo que impida que "-rf" funcione.
Muchos ya han declarado la siguiente solución:
cp --remove-destination `readlink file` file
Sin embargo, esto no funcionará en directorios simbólicamente vinculados.
Agregar un recursivo y la fuerza tampoco funcionará:
cp -rf --remove-destination `readlink file` file
cp: no puede copiar un directorio, ''ruta / archivo, en sí mismo,'' archivo ''
Por lo tanto, probablemente sea más seguro eliminar el enlace simbólico por completo primero:
resolve-symbolic-link() {
if [ -L $1 ]; then
temp="$(readlink "$1")";
rm -rf "$1";
cp -rf "$temp" "$1";
fi
}
No es exactamente una frase única como esperabas, pero ponla en tu entorno shell, y puede ser.
No hay necesidad de utilizar scripts de shell divertidos, rsync
ni opciones especiales de GNU en cp
. Muy simple:
$ mv target link
Si no conocemos el objetivo, sustituimos la expresión $(readlink link)
por el target
anterior:
$ mv $(readlink link) link
La utilidad mv
corresponde a la llamada de sistema de rename
nombre en sistemas similares a POSIX (al menos cuando no se opera a través de diferentes volúmenes de sistemas de archivos). La llamada al sistema rename
elimina el objeto de destino, si existe, en una sola operación.
Podemos simplemente mv
el archivo objetivo al enlace simbólico:
$ touch target
$ ln -sf target link
$ ls -l target link
lrwxrwxrwx 1 kaz kaz 6 Sep 7 2016 link -> target
-rw-rw-r-- 1 kaz kaz 0 Sep 7 2016 target
$ mv target link
$ ls -l target link
ls: cannot access target: No such file or directory
-rw-rw-r-- 1 kaz kaz 0 Sep 7 2016 link
Si hacemos esto a través de volúmenes, se simula. El GNU Coreutils mv
primero intenta rename
llamada al sistema. Cuando eso falla, usa la función unlink
para eliminar el enlace simbólico de destino y realiza una copia:
$ touch /tmp/target
$ ln -sf /tmp/target link
$ ls -l /tmp/target link
lrwxrwxrwx 1 kaz kaz 11 Sep 7 2016 link -> /tmp/target
-rw-rw-r-- 1 kaz kaz 0 Sep 7 16:20 /tmp/target
$ strace mv /tmp/target link
[ ... snip ... ]
stat("link", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("/tmp/target", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("link", {st_mode=S_IFLNK|0777, st_size=11, ...}) = 0
rename("/tmp/target", "link") = -1 EXDEV (Invalid cross-device link)
unlink("link") = 0
open("/tmp/target", O_RDONLY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
open("link", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 65536) = 0
[ ... ]
close(0) = 0
close(1) = 0
exit_group(0) = ?
+++ exited with 0 +++
$ ls -l /tmp/target link
ls: cannot access /tmp/target: No such file or directory
-rw-rw-r-- 1 kaz kaz 0 Sep 7 16:20 link
No hay un solo comando para convertir un enlace simbólico en un archivo normal. La forma más directa es usar el enlace de lectura para encontrar el archivo al que apunta un enlace simbólico y luego copiar ese archivo sobre el enlace simbólico:
cp --remove-destination `readlink bar.pdf` bar.pdf
Por supuesto, si bar.pdf
es, de hecho, un archivo regular para comenzar, entonces esto va a obstruir el archivo. Por lo tanto, sería aconsejable un cierto control de cordura.
No hay un solo comando. Pero si no quiere una copia y todo lo que quiere es otra referencia, puede reemplazar el enlace simbólico por un enlace (también conocido como "enlace duro"). Esto solo funciona si están en la misma partición, por cierto.
rm filename
ln target filename
Otro enfoque si se encuentra haciendo esto a menudo es adaptar la respuesta de kbrock a un script de shell y ponerla en / usr / bin /. Algo a lo largo de las líneas de:
if [ $# -ne 1 ]
then
echo "Usage: $0 filename"
exit 1
fi
[ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"
chmod + x it, y luego ejecutarlo como un comando normal.
Para archivos de texto, el comando sed
puede hacer esto en una línea si lo pasa al interruptor en el lugar ( -i
). Esto se debe a que sed
realiza una sola pasada sobre un archivo, lo que convierte la salida en un archivo temporal que posteriormente renombra para que coincida con el original.
Simplemente haga un sed
línea sin transformaciones:
sed -i '';'' /path/to/symbolic/link
Rsync puede deferencia nativa el enlace simbólico para usted utilizando -L bandera.
[user@workstation ~]$ rsync -h | grep -- -L
-L, --copy-links transform symlink into referent file/dir
Sería tan simple como: rsync -L <symlink> <destination>
Solo una repetición de las respuestas de otros, pero agregar la "comprobación de validez" para garantizar que el enlace pasado sea en realidad un enlace simbólico:
removelink() {
[ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"
}
Esto significa que si el archivo es un enlace simbólico, ejecute el comando de copia.
en caso de enlaces simbólicos "relativos", podría agregar una declaración awk a @jared answer:
for f in $(find . -type l); do /bin/cp -rf --remove-destination -f $(find . /! -type l -name $(readlink $f | awk -F"../" ''{print $NF}'')) $f;done;
Si tiene enlaces simbólicos que apuntan a directorios, debe utilizar un enfoque más radical porque cp --remove-destination no funciona junto con los directorios de enlaces simbólicos correctamente.
for f in `find . -type l`; do (cd `dirname $f`; target=`basename $f`; source=`readlink $target` ; rm -rf $target && cp -r $source $target); done
Seguro que esto podría escribirse con menos gastos generales. Pero es bastante bueno leer en mi opinión.
cp puede eliminar el archivo de destino:
cp --remove-destination target filename
for f in $(find -type l);do cp --remove-destination $(readlink $f) $f;done;
- Verifique los enlaces simbólicos en el directorio actual y los subdirectorios
find -type l
- Obtener la ruta del archivo vinculado
readlink $f
- Elimine el enlace simbólico y copie el archivo
cp --remove-destination $(readlink $f) $f