¿Hay alguna manera fácil de reemplazar todos los enlaces simbólicos con el archivo al que se vinculan?
¿Hay alguna manera fácil de reemplazar todos los enlaces simbólicos con el archivo al que se vinculan?
Respuestas:
Para algunas definiciones de "fácil":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Ejecute este script con nombres de enlaces como argumentos, por ejemplo, a través de find . -type l -exec /path/tos/script {} +
"$var"
a "${var}"
es un noop en sh / bash. Eliminé el bashism ( [[
), el resto es compatible con POSIX sh.
cp
un archivo temporal en el mismo directorio y luego mv -f
ese archivo temporal en el original. Esto debería evitar problemas como personas que se mantienen presionadas Ctrl-C
o que el sistema de archivos se llene entre los comandos rm
y cp
(evitando así que incluso los nuevos ln
funcionen). Los nombres de archivo temporales son fáciles de detectar ls -a
para una limpieza posterior si es necesario.
abstarget=$(readlink -f "$link")
lugar del bloque de casos , sino que podría haber sido por razones de portabilidad.
Puede ser más fácil usar tar para copiar los datos a un nuevo directorio.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Podrías usar algo como esto
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
es la solución más simple
cp
implementaciones copiarán directorios.
Si te entendí correctamente, la -L
bandera del cp
comando debería hacer exactamente lo que quieres.
Simplemente copie todos los enlaces simbólicos y los reemplazará con los archivos a los que apuntan.
cp -L files tmp/ && rm files && cp tmp/files .
si aclaras, probablemente ayudarás a más personas ...
"fácil" será una función tuya, muy probablemente.
Probablemente escribiría un script que usa la utilidad de línea de comando "find" para encontrar archivos vinculados simbólicamente, luego llama a rm y cp para eliminar y reemplazar el archivo. Probablemente harías bien en hacer que la acción llamada por find compruebe que queda suficiente espacio libre antes de mover también el enlace sym.
Otra solución puede ser montar el sistema de archivos en cuestión a través de algo que oculta los enlaces simbólicos (como samba), luego simplemente copie todo. Pero en muchos casos, algo así introduciría otros problemas.
Una respuesta más directa a su pregunta es probablemente "sí".
Editar: según la solicitud de información más específica. De acuerdo con la página de manual de find , este comando enumerará todos los archivos de enlace sym en una profundidad de 2 directorios, desde /:
find / -maxdepth 2 -type l -print
Para obtener find para ejecutar algo al encontrarlo:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Creo que llamará a un script que acabo de inventar y pasará el nombre de archivo que acaba de encontrar. Alternativamente, puede capturar la salida de búsqueda al archivo (use "find [blah]> symlinks.data", etc.) y luego pasar ese archivo a un script que haya escrito para manejar la copia sobre el original con gracia.
-exec ./ReplaceSymLink.sh {} \;
Este es el oneliner que he usado: suponga que todos los archivos locales son enlaces a otro archivo en "fuente". Puede refinar la selección de archivos con patrones o "buscar". Por favor, comprenda antes de usar.
para f en *; do cp --remove-destination source / $ f $ f; hecho
Espero que esto ayude
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Hará una copia de cada archivo / carpeta con enlace simbólico <filename>.dereferenced
, que es más seguro (si es menos conveniente) que simplemente reemplazarlos directamente. Mover los datos copiados a los nombres de archivo de los enlaces simbólicos se deja como ejercicio para el lector.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
basado en /superuser//a/1301199/499386 de MastroGeppetto
Hay muchas buenas respuestas allí, pero desde que estabas buscando algo fácil
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
Tuve el mismo problema con la copia de enlaces de gwenview cuando normalmente esperarías que siguiera el enlace y copiara el archivo.
Lo que hice para 'limpiar' el directorio siguiendo todos los enlaces y copiando todos los archivos apuntados al directorio, fue crear un directorio temporal, ejecutar, por ejemplo
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
Esto es demasiado peligroso para poner en un script ya que no hay verificación pero solucionó mi problema.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Hice una versión de una línea, ya que mi hotel web no permitía bash-scripts y funcionó bien para mí:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0