rsync ciertos archivos, excluyendo el resto, ignorando el directorio .svn /, recursivamente

19

Estoy usando rsyncpara copiar algunos archivos de un recurso compartido a otro.

Recurrentemente, necesito:

  • Eliminar archivos en el destino que se eliminaron del origen
  • Solo sincronización .phpy .jsarchivos
  • Excluir cualquier otro tipo de archivo
  • No elimine .svn/directorios en el destino

Si uso esto:

rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \
    /origin /destination

Entonces rsyncno es recursivo porque exclude="*"excluye todos los archivos pero también las carpetas.

Si agrego --include="*/", el .svn/directorio se elimina (también se incluye).

¿Cómo puedo resolver este dilema de explosión mental?

uname -a:

Linux tux 3.9.2-1-ARCH # 1 SMP PREEMPT sáb 11 de mayo 20:31:08 CEST 2013 x86_64 GNU / Linux

rsync versión:

rsync 3.0.9-6
canolucas
fuente

Respuestas:

13

1er intento (no funcionó)

Debe incluir los directorios además de los archivos:

rsync -zavC --delete --include '*/' --include='*.php' --include='*.js' \
     --exclude="*" /media/datacod/Test/ /home/lucas/Desktop/rsync/

2do intento

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/

datos de prueba

Escribí este script para crear algunos datos de muestra para probar esto. Aquí está ese guión setup_svn_sample.bash:

#!/bin/bash

# setup .svn dirs
mkdir -p dir{1,2}/dir{1,2,3,4}/.svn

# fake data under .svn
mkdir -p dir1/dir{1,2,3,4}/.svn/origdir
mkdir -p dir2/dir{1,2,3,4}/.svn/keepdir

# files to not sync
touch dir1/dir{1,2,3,4}/file{1,2}

# files to sync
touch dir1/dir{1,2,3,4}/file1.js
touch dir1/dir{1,2,3,4}/file1.php

Ejecutarlo produce los siguientes directorios:

dir fuente

$ tree -a dir1
dir1
|-- dir1
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir2
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir3
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
`-- dir4
    |-- file1
    |-- file1.js
    |-- file1.php
    |-- file2
    `-- .svn
        `-- origdir

dir de destino

$ tree -a dir2
dir2
|-- dir1
|   `-- .svn
|       `-- keepdir
|-- dir2
|   `-- .svn
|       `-- keepdir
|-- dir3
|   `-- .svn
|       `-- keepdir
`-- dir4
    `-- .svn
        `-- keepdir

Ejecutando el rsynccomando anterior :

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
dir1/file1.js
dir1/file1.php
dir2/file1.js
dir2/file1.php
dir3/file1.js
dir3/file1.php
dir4/file1.js
dir4/file1.php

sent 480 bytes  received 168 bytes  1296.00 bytes/sec
total size is 0  speedup is 0.00

Afirrards dir2 resultantes:

$ tree -a dir2
dir2
|-- dir1
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir2
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir3
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
`-- dir4
    |-- file1.js
    |-- file1.php
    `-- .svn
        `-- keepdir

Por que funciona

La pieza clave de este script es hacer uso de la capacidad de filtros de rsync. Los filtros le permiten eliminar archivos del conjunto coincidente en varios puntos del comando. Entonces, en nuestro caso, estamos filtrando cualquier archivo que coincida con el patrón */.svn*. Los modificadores le -rs_dicen al filtro que queremos filtrar tanto en el lado fuente como en el lado objetivo.

extracto de la sección NOTAS DEL FILTRO de la página de manual de rsync

  • Se usa una s para indicar que la regla se aplica al lado emisor. Cuando una regla afecta al lado emisor, evita que se transfieran archivos. El valor predeterminado es que una regla afecte a ambos lados a menos que --delete-excludedse especifique, en cuyo caso las reglas predeterminadas se convierten solo en el lado del remitente. Consulte también las reglas de ocultar (H) y mostrar (S), que son una forma alternativa de especificar las inclusiones / exclusiones del lado emisor.

  • Se usa una r para indicar que la regla se aplica al lado receptor. Cuando una regla afecta al lado receptor, evita que se eliminen los archivos. Vea el modificador s para más información. Consulte también las reglas de protección (P) y riesgo (R), que son una forma alternativa de especificar las inclusiones / exclusiones del lado del receptor.

Ver man rsync para más detalles.

Consejos para resolver esto (sugerencia usando --dry-run)

Mientras describía cómo hacer esto, pensé en mencionar el --dry-runcambio a rsync. Es extremadamente útil para ver lo que sucederá sin que rsyncrealmente tenga lugar.

Por ejemplo

El uso del siguiente comando hará una ejecución de prueba y nos mostrará la lógica de decisión detrás rsync:

rsync --dry-run -avvzC --filter='-rs_*/.svn*' --include="*/" \
     --include='*.js' --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
[sender] showing directory dir3 because of pattern */
[sender] showing directory dir2 because of pattern */
[sender] showing directory dir4 because of pattern */
[sender] showing directory dir1 because of pattern */
[sender] hiding file dir1/file1 because of pattern *
[sender] showing file dir1/file1.js because of pattern *.js
[sender] hiding file dir1/file2 because of pattern *
[sender] showing file dir1/file1.php because of pattern *.php
[sender] hiding directory dir1/.svn because of pattern */.svn*
[sender] hiding file dir2/file1 because of pattern *
[sender] showing file dir2/file1.js because of pattern *.js
[sender] hiding file dir2/file2 because of pattern *
[sender] showing file dir2/file1.php because of pattern *.php
[sender] hiding directory dir2/.svn because of pattern */.svn*
[sender] hiding file dir3/file1 because of pattern *
[sender] showing file dir3/file1.js because of pattern *.js
[sender] hiding file dir3/file2 because of pattern *
[sender] showing file dir3/file1.php because of pattern *.php
[sender] hiding directory dir3/.svn because of pattern */.svn*
[sender] hiding file dir4/file1 because of pattern *
[sender] showing file dir4/file1.js because of pattern *.js
[sender] hiding file dir4/file2 because of pattern *
[sender] showing file dir4/file1.php because of pattern *.php
[sender] hiding directory dir4/.svn because of pattern */.svn*
delta-transmission disabled for local transfer or --whole-file
[generator] risking directory dir3 because of pattern */
[generator] risking directory dir2 because of pattern */
[generator] risking directory dir4 because of pattern */
[generator] risking directory dir1 because of pattern */
[generator] protecting directory dir1/.svn because of pattern */.svn*
dir1/file1.js
dir1/file1.php
[generator] protecting directory dir2/.svn because of pattern */.svn*
dir2/file1.js
dir2/file1.php
[generator] protecting directory dir3/.svn because of pattern */.svn*
dir3/file1.js
dir3/file1.php
[generator] protecting directory dir4/.svn because of pattern */.svn*
dir4/file1.js
dir4/file1.php
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 231 bytes  received 55 bytes  572.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

En el resultado anterior, puede ver que los ./svndirectorios están protegidos por nuestra regla de filtro. Información valiosa para depurar el rsync.

Referencias

slm
fuente
Ya probé esto, como dije anteriormente. Si hago esto, entonces el directorio .SVN también se incluye (muy probablemente eliminado, porque no existe en el origen, o modificado). Es crítico dejar el directorio .SVN intacto. Gracias por el intento de todos modos! :)
canolucas
-C se supone que debe ignorar ".SVN /", pero lo include="*/"incluye
canolucas
Tienes razón. Debería ser .svn, editando la respuesta. De todos modos, después de renombrar el problema persiste. -Cy include="*/"no parecen ser muy amigos :(
canolucas
10

Ok, después de varios intentos lo resolví:

rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' \
    --include='*/' --exclude='*' --prune-empty-dirs \
    --filter "protect .svn/" /origin /destination

Gracias

canolucas
fuente
Gran respuesta. Mi filtro protege los .svn/directorios --prune-empty-dirsen caso de que estén vacíos. Otro enfoque, este duplicando rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' --include='*/' --exclude='*' /origin /destination
directorios
La clave de mi enfoque es --exclude=.svn/antes de los --include's
canolucas
Buena respuesta también. Hubiera sugerido un exclude = '. Svn /' pero pensé que querías usar el -C. ¡Me alegra que lo hayas descubierto!
slm
0

Aunque esto no está usando rsync, otra opción es usar find y cpio. Por ejemplo, tengo un directorio llamado Fotos y ese año y mes.

Photos
├── 2002
   ├── 2002-03
      ├── 2002-03-30
      ├── 2002-03-31
      └── 2002-03-31-02
   ├── 2002-04
      ├── 2002-04-01
      ├── 2002-04-01-03
      ├── 2002-04-07
      ├── 2002-04-21
      ├── 2002-04-22
      ├── 2002-04-22-02
      └── 2002-04-27
   ├── 2002-05
      ├── 2002-05-02
      ├── 2002-05-03

Pero aquí tengo jpg, dng, xml y otras cosas y solo quiero los jpg, así que haría esto

"cd" al directorio sobre el directorio de Fotos y luego:

find Photos -type f -name "*jpg" -print | cpio -pdmvu /fast

Y se va

/fast/Photos/2002/2002-04/2002-04-22/bath problem.jpg
/fast/Photos/2002/2002-04/2002-04-22-02/full bath.jpg
/fast/Photos/2002/2002-07/2002-07-10/Broken Top.jpg
/fast/Photos/2002/2002-12/2002-12-28/101-0125_IM~~G.jpg
/fast/Photos/2002/2002-12/2002-12-28/small-101-0125_IM~~G.jpg
/fast/Photos/2003/2003-01/2003-01-19/k1.jpg
/fast/Photos/2003/2003-01/2003-01-19/k2.jpg
/fast/Photos/2003/2003-02/2003-02-23/quinn.jpg
/fast/Photos/2003/2003-05/2003-05-04/all.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0015_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_2_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0007_2_r1.jpg

Puede usar este método para muchas cosas, hace años así es como copiamos el sistema de archivos / cuando nos movemos a discos más grandes, ya que copiaría los archivos del dispositivo.

lxtwin
fuente
Eso no responde la pregunta.
RalfFriedl
Lo hace si usa: find / origin -type f (-name " .php" -o -name " .js") -print | cpio -pdmvu / destination Solo los archivos * .php y * .js estarán en el directorio de destino.
lxtwin