Tengo dos unidades con los mismos archivos, pero la estructura de directorios es totalmente diferente.
¿Hay alguna forma de "mover" todos los archivos en el lado de destino para que coincidan con la estructura del lado de origen? ¿Quizás con un guión?
Por ejemplo, la unidad A tiene:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Mientras que la unidad B tiene:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
Los archivos en cuestión son enormes (800 GB), por lo que no quiero volver a copiarlos; Solo quiero sincronizar la estructura creando los directorios necesarios y moviendo los archivos.
Estaba pensando en una secuencia de comandos recursiva que encontraría cada archivo de origen en el destino, luego lo movería a un directorio coincidente y lo crearía si fuera necesario. Pero, ¡eso está más allá de mis habilidades!
Aquí se proporcionó otra solución elegante:
https://superuser.com/questions/237387/any-way-to-sync-directory-structure-when-the-files-ya-are-on-both-sides /238086
Respuesta aceptada:
Iré con Gilles y te indicaré Unison como lo sugirió hasen j. Unison fue DropBox 20 años antes que DropBox. Código sólido como una roca que mucha gente (incluido yo mismo) usa todos los días; vale la pena aprenderlo. Aún así, join
necesita toda la publicidad que pueda conseguir 🙂
Esta es solo la mitad de una respuesta, pero tengo que volver al trabajo 🙂
Básicamente, quería demostrar el poco conocido join
utilidad que hace exactamente eso:une dos tablas en un campo.
Primero, configure un caso de prueba que incluya nombres de archivos con espacios:
for d in a b 'c c'; do mkdir -p "old/$d"; echo $RANDOM > "old/${d}/${d}.txt"; done
cp -r old new
(edite algunos directorios y/o nombres de archivos en new
).
Ahora, queremos construir un mapa:hash -> nombre de archivo para cada directorio y luego usar join
para unir archivos con el mismo hash. Para generar el mapa, coloque lo siguiente en makemap.sh
:
find "$1" -type f -exec md5 -r "{}" ;
| sed "s/([a-z0-9]*) ${1}/(.*)/1 "2"/"
makemap.sh
escupe un archivo con líneas de la forma, 'hash "nombre de archivo"', por lo que simplemente nos unimos en la primera columna:
join <(./makemap.sh 'old') <(./makemap.sh 'new') >moves.txt
Esto genera moves.txt
que se ve así:
49787681dd7fcc685372784915855431 "a/a.txt" "bar/a.txt"
bfdaa3e91029d31610739d552ede0c26 "c c/c c.txt" "c c/c c.txt"
El siguiente paso sería hacer los movimientos, pero mis intentos se atascaron al citar... mv -i
y mkdir -p
debería ser útil.