Me gustaría copiar un conjunto de archivos del directorio A al directorio B, con la advertencia de que si un archivo en el directorio A es idéntico a un archivo en el directorio B, ese archivo no debe copiarse (y, por lo tanto, su tiempo de modificación no debe ser actualizado). ¿Hay alguna manera de hacerlo con las herramientas existentes, sin escribir mi propio script para hacerlo?
Para elaborar un poco sobre mi caso de uso: estoy autogenerando un montón de .carchivos en un directorio temporal (por un método que tiene que generarlos incondicionalmente), y cuando los vuelva a generar, me gustaría copiar solo los que han cambiado al directorio de origen real, dejando intactos los que no han cambiado (con sus viejos tiempos de creación) para que makesepa que no es necesario volver a compilarlos. (Sin .cembargo, no todos los archivos generados son archivos, así que necesito hacer comparaciones binarias en lugar de comparaciones de texto).
(Como nota: esto surgió de la pregunta que hice en https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 , donde estaba intentando para acelerar el archivo de script que estaba usando para hacer esta operación, pero se me ocurre que realmente debería preguntar si hay una mejor manera de hacerlo que escribir mi propio script, especialmente porque cualquier forma simple de hacerlo en un shell el script invocará algo así como cmpen cada par de archivos, y comenzar todos esos procesos lleva demasiado tiempo).
fuente

diff -qr dirA dirBpara ver qué archivos son únicosdirAydirB, respectivamente.rsync -avnco a lo largorsync --archive --verbose --dry-run --checksum.Respuestas:
rsync es probablemente la mejor herramienta para esto. Hay muchas opciones en este comando, así que lea la página de manual . Creo que quieres la opción --checksum o la --ignore-times
fuente
-tse especifica la opción) o al tiempo de sincronización (si-tno se especifica)rsyncno. Si hago esto:mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* dest, a continuación,stat dest/amuestra su -mtime y ctime son 5 segundos más antiguas que las desrc/a.--checksumopción, y aunque linux.die.net/man/1/rsync no contiene absolutamente nada que implique que tenga algún efecto sobre si la fecha de modificación se actualiza, no obstante, deja la fecha de modificación de destino. intacto (Por otro lado, la--ignore-timesopción no tiene este efecto; con ella, la fecha de modificación aún se actualiza). Dado que esto parece estar completamente indocumentado, ¿puedo confiar en ello?rsyncel flujo de trabajo es: 1) verificar si el archivo necesita ser actualizado; 2) si es así, actualice el archivo. La--checksumopción dice que no debe actualizarse, por lorsyncque no debe continuar con el paso 2).--ignore-timessin--checksumcopiaría todos los archivos, y también actualizaría la marca de tiempo, incluso si los archivos son idénticos.Puedes usar el
-uinterruptor para que tecpguste:Desde la página del manual:
fuente
-ubandera y cómo funciona y cómo esto ayudaría al OP. Sin embargo, en este caso particular, no ayudaría al OP ya que copiaría archivos idénticos si fueran más nuevos y cambiaría sus marcas de tiempo, que es precisamente lo que el OP quiere evitar.Si bien el uso
rsync --checksumes una buena forma general de "copiar si se cambia", en su caso particular, ¡hay una solución aún mejor!Si desea evitar la recompilación innecesaria de archivos, ¡debe usar ccache, que fue creado exactamente para este propósito! De hecho, no solo evitará recompilaciones innecesarias de sus archivos generados automáticamente, sino que también acelerará las cosas cada vez que lo haga
make cleany volverá a compilar desde cero.A continuación, estoy seguro de que preguntarás: "¿Es seguro?" Bueno, sí, como señala el sitio web:
Y es fácil de usar simplemente agregándolo como un prefijo en la
CC=línea de su archivo MAKE (o puede usar enlaces simbólicos, pero la forma del archivo MAKE probablemente sea mejor).fuente
ccache file.c -o file.oo su equivalente, varios cientos de veces porque hay varios cientos defile.carchivos. Cuando estaba haciendo eso concmp, en lugar de hacerloccache, me llevó varios minutos, ycmpes tan liviano comoccache. El problema es que, en Cygwin, iniciar un proceso lleva un tiempo no despreciable, incluso para un proceso completamente trivial.for f in src/*; do /bin/true.exe; donelleva 30 segundos, así que sí. De todos modos, prefiero mi editor basado en Windows, y aparte de este tipo de problema de sincronización, Cygwin funciona bastante bien con mi flujo de trabajo como el lugar liviano para probar cosas localmente si no estoy cargando en los servidores de compilación. Es útil tener mi shell y mi editor en el mismo sistema operativo. :)Esto debería hacer lo que necesitas
Dónde:
fuente
-Jes específico de bsd; con GNU xargs lo es-I), y no funciona correctamente si el mismo conjunto de archivos ya no existe en ambas ubicaciones (sitouch x/booentonces grep me daOnly in ./x: booque causa errores en la tubería). Use una herramienta creada para el trabajo, comorsync --checksum.Me gusta usar unison a favor
rsyncporque es compatible con múltiples maestros, ya que configuré mis claves ssh y vpn por separado.Entonces, en mi crontab de solo un host, los dejo sincronizar cada 15 minutos:
Entonces puedo estar desarrollando en ambos lados y los cambios se propagarán. De hecho, para proyectos importantes, tengo hasta 4 servidores que reflejan el mismo árbol (3 ejecutan al unísono desde cron, señalando al que no lo hace). De hecho, los hosts Linux y Cygwin son mixtos, excepto que no espere sentido de enlaces blandos en win32 fuera del entorno cygwin.
Si sigue esta ruta, haga el espejo inicial en el lado vacío sin el
-batch, es decirPor supuesto, hay una configuración para ignorar los archivos de respaldo, archivos, etc.
fuente
unisonopción que significa "no actualizar las fechas de última modificación del archivo". ¿Hay uno? De lo contrario, esta es una gran respuesta a un problema completamente diferente.-timeshace eso por mi Unison también tiene un modo de marcha en seco, creo.times=false(o dejar-times) haría eso. No sé cómo me perdí eso en la documentación antes. ¡Gracias!Si bien
rsync --checksumes la respuesta correcta, tenga en cuenta que esta opción es incompatible--timesy que--archiveincluye--times, por lo que si lo desearsync -a --checksum, realmente necesita hacerlorsync -a --no-times --checksum.fuente