Quiero crear una "copia" de un árbol de directorios donde cada archivo es un enlace al archivo original
Ejemplo: tengo una estructura de directorio:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
Aquí está el resultado esperado, una "copia" del árbol de directorios donde cada archivo es un enlace rígido al archivo original:
dirB/ # normal directory
dirB/file1 # hardlink to dirA/file1
dirB/x/ # normal directory
dirB/x/file2 # hardlink to dirA/x/file2
dirB/y/ # normal directory
dirB/y/file3 # hardlink to dirA/y/file3
pax
, como en FreeBSD,cp -a
no enlaza los enlaces simbólicos.POSIXY, usaría
pax
en modo lectura + escritura con la-l
opción:(
-pe
Conserva todos los atributos posibles de archivos (en este caso sólo directorios) que se copian, como GNUcp
's-a
hace).Ahora, aunque estándar , ese comando no es necesariamente muy portátil .
Primero, muchos sistemas basados en GNU / Linux no se incluyen
pax
por defecto (a pesar de que es una utilidad POSIX no opcional).Luego, varios errores y no conformidades con algunas implementaciones causan varios problemas con ese código.
pax
(al menos) no funciona cuando se usa-rwl
en combinación con-s
. Por alguna razón, parece que aplica la sustitución tanto a la ruta original como a la copiada. Así que arriba, intentaría hacer algo enlink("dirB/file", "dirB/file")
lugar delink("dirA/file", "dirB/file")
.pax
no crea enlaces duros para archivos de tipo enlace simbólico (un comportamiento permitido por POSIX). No solo eso, sino que también aplica la sustitución a los objetivos de los enlaces simbólicos (un comportamiento no permitido por POSIX). Entonces, por ejemplo, si hay unfoo -> AA
enlace simbólicodirA
, se convertiráfoo -> BA
endirB
.Además, si desea hacer lo mismo pero con rutas de archivos arbitrarias cuyo contenido está almacenado
$src
y$dst
, es importante darse cuenta de quepax -rwl -- "$src" "$dst"
crea la estructura de directorio completa de$src
dentro$dst
(que tiene que existir y ser un directorio). Por ejemplo, si$src
esfoo/bar
, entonces,$dst/foo/bar
se crea.Si, en cambio, desea
$dst
ser una copia de$src
, lo más fácil es probablemente hacerlo como:(que también solucionaría la mayoría de los problemas mencionados anteriormente, pero fallaría si la ruta absoluta de
$dst
termina en caracteres de nueva línea).Ahora eso no ayudará en los sistemas GNU / Linux donde no hay
pax
.Es interesante notar que
pax
fue creado por POSIX para fusionar las características de los comandostar
ycpio
.cpio
es un comando histórico de Unix (de 1977) en oposición a una invención POSIX, y también hay una implementación de GNU (no unapax
). Entonces, aunque ya no es un comando estándar (aunque estaba en SUSv2), sigue siendo muy común y hay un conjunto básico de características en las que generalmente puede confiar.El equivalente de
pax -rwl
seríacpio -pl
. Sin embargo:cpio
toma la lista de archivos de entrada en stdin en lugar de argumentos (nueva línea delimitada, lo que significa que los nombres de archivo con caracteres de nueva línea no son compatibles)find
(find
ycpio
fueron desarrollados conjuntamente por las mismas personas)).cpio
implementaciones tienen opciones para preservar algunas, pero nada portátil).Entonces con
cpio
:fuente
-s /A/B
reemplazaA
conB
para que sedirA
conviertadirB
. Si el nombre del directorio de origen no tieneA
, entonces eso lo copiará (vinculará) sobre sí mismo. Vea también el resto de la respuesta para posibles enfoques mejores.Respuesta corta:
fuente
En caso de que esté buscando esa función de copiar con enlaces duros para hacer instantáneas o copias de seguridad de (todos o parte de) sus archivos, eche un vistazo
rsnapshot
.fuente
La respuesta de @ gudmundur-orn es correcta, pero si estás en BtrFS en Linux
cp a --reflink=auto dirA dirB
debería hacer el truco, con la diferencia de que los archivos son realmente diferentes y cambiar uno no cambia el otro. Puede lograr casi lo mismo concp -c
una Mac con APFS (auto
hará una copia completa si no es posible,-c
fallará).Cualquier sistema de archivos COW debería poder hacerlo, pero los proveedores no han acordado una opción de línea de comando estándar.
fuente