¿Cómo rsync solo una lista específica de archivos?

95

Tengo alrededor de 50 archivos en varios subdirectorios que me gustaría enviar a un servidor remoto. Pensé que rsync podría hacer esto por mí usando la opción --include-from. Sin la opción --exclude = "*", todos los archivos del directorio se sincronizan, con la opción, no hay archivos.

rsync -avP -e ssh --include-from=deploy/rsync_include.txt --exclude=* ./ [email protected]:/var/www/ --dry-run

Lo estoy ejecutando como seco inicialmente y 0.0.0.0 obviamente se reemplaza por la IP del servidor remoto. El contenido de rsync_include.txt es una nueva lista separada por líneas de rutas relativas a los archivos que quiero cargar.

¿Hay una mejor manera de hacer esto que se me escape un lunes por la mañana?

Dan Steele
fuente

Respuestas:

4

Editar: La respuesta de Josip Rodin a continuación es mejor. ¡Por favor use ese!

Es posible que le resulte más fácil, si está buscando una lista específica de archivos, colocándolos directamente en la línea de comando:

# rsync -avP -e ssh `cat deploy/rsync_include.txt` [email protected]:/var/www/

Esto supone, sin embargo, que su lista no es tan larga que la longitud de la línea de comando será un problema y que el rsync_include.txtarchivo contiene solo rutas reales (es decir, sin comentarios ni expresiones regulares).

Wes Hardaker
fuente
9
Desafortunadamente, esto no funciona con una lista grande o con archivos con espacios en el nombre.
Wes Modes
3
[Lista de argumentos demasiado larga]
Dankó Dávid
De forma predeterminada, xargs agrega argumentos de stdin al final de la línea de comando. Eso no funciona ya que rsync necesita que el último argumento sea el destino. Algunas versiones de xargs pueden opcionalmente insertar argumentos en el medio de la línea de comando. Eso debería funcionar siempre que no le importe que pueda ejecutar rsync más de una vez cuando la lista de archivos sea larga. En cualquier caso, rsync --files-fromprobablemente sea una solución más fácil y confiable :)
Lassi
Wes Hardaker: ¿Tu edición y referencia a la "respuesta de Josip Rodin" se refiere realmente a la respuesta de @atp que editó Rodin?
Seamus
234

Hay una bandera --files-fromque hace exactamente lo que quieres. De man rsync:

--files-from=FILE

El uso de esta opción le permite especificar la lista exacta de archivos para transferir (como se lee del ARCHIVO especificado o - para la entrada estándar). También modifica el comportamiento predeterminado de rsync para facilitar la transferencia solo de los archivos y directorios especificados:

  • La opción --relative (-R) está implícita, que conserva la información de ruta que se especifica para cada elemento en el archivo (use --no-related o --no-R si desea desactivarlo).

  • La opción --dirs (-d) está implícita, que creará directorios especificados en la lista en el destino en lugar de omitirlos ruidosamente (use --no-dirs o --no-d si desea desactivar eso).

  • El comportamiento de la opción --archive (-a) no implica --recursive (-r), así que especifíquelo explícitamente, si lo desea.

  • Estos efectos secundarios cambian el estado predeterminado de rsync, por lo que la posición de la opción --files-from en la línea de comandos no influye en cómo se analizan otras opciones (por ejemplo, -a funciona igual antes o después de --files- from, al igual que --no-R y todas las demás opciones).

Los nombres de archivo que se leen del ARCHIVO son todos relativos al directorio de origen; se eliminan las barras inclinadas iniciales y no se permite que las referencias ".." superen el directorio de origen. Por ejemplo, tome este comando:

rsync -a --files-from=/tmp/foo /usr remote:/backup

Si / tmp / foo contiene la cadena "bin" (o incluso "/ bin"), el directorio / usr / bin se creará como / backup / bin en el host remoto. Si contiene "bin /" (tenga en cuenta la barra inclinada), también se enviará el contenido inmediato del directorio (sin necesidad de mencionarlo explícitamente en el archivo; esto comenzó en la versión 2.6.4). En ambos casos, si la opción -r estuviera habilitada, la jerarquía completa de ese directorio también se transferiría (tenga en cuenta que -r debe especificarse explícitamente con --files-from, ya que no está implícito en -a). También tenga en cuenta que el efecto de la opción relativa (habilitada de forma predeterminada) es duplicar solo la información de ruta que se lee del archivo; no fuerza la duplicación de la ruta de especificación de origen (/ usr en este caso) .

Además, el archivo --files-from se puede leer desde el host remoto en lugar del host local si especifica un "host:" delante del archivo (el host debe coincidir con un extremo de la transferencia). Como atajo, puede especificar solo un prefijo de ":" para significar "usar el extremo remoto de la transferencia". Por ejemplo:

rsync -a --files-from=:/path/file-list src:/ /tmp/copy

Esto copiaría todos los archivos especificados en el archivo / ruta / lista de archivos que estaba ubicado en el host remoto "src".

Si se especifican las opciones --iconv y --protect-args y los nombres de archivo --files-from se envían de un host a otro, los nombres de archivo se traducirán del juego de caracteres del host emisor al juego de caracteres del host receptor.

NOTA: ordenar la lista de archivos en la entrada --files-from ayuda a rsync a ser más eficiente, ya que evitará volver a visitar los elementos de la ruta que se comparten entre las entradas adyacentes. Si la entrada no está ordenada, algunos elementos de ruta (directorios implícitos) pueden terminar siendo escaneados varias veces, y rsync eventualmente los duplicará después de que se conviertan en elementos de lista de archivos.

atp
fuente
23
Tenga en cuenta que todavía tiene que especificar el directorio donde se encuentran los archivos enumerados, por ejemplo: rsync -av --files-from=file-list . target/para copiar archivos del directorio actual.
Nicolas Mattia
7
Sí, y reiterar: The filenames that are read from the FILE are all relative to the source dir.
atp
¡Ah, me perdí eso, lo siento!
Nicolas Mattia
1
si el archivo file-from tiene algo que comience con ..rsync, parece ignorar el ..mensaje que me da un error como rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory(en este caso, ejecutar desde el directorio "test" e intentar especificar "../subdir/test.txt" que sí existe.
Michael
¿Se --files-frompuede combinar el argumento con una lista explícita de incluye y excluye, y los archivos de la lista agregados con --files-fromanularán las reglas de exclusión existentes, de modo que se incluyan si aparecen en el archivo?
highsciguy
13

--files-from=El parámetro necesita una barra diagonal si desea mantener intacta la ruta absoluta. Entonces su comando se convertiría en algo como a continuación:

rsync -av --files-from=/path/to/file / /tmp/

Esto podría hacerse como si hubiera una gran cantidad de archivos y desea copiar todos los archivos a la ruta x. Entonces, buscaría los archivos y arrojaría la salida a un archivo como el siguiente:

find /var/* -name *.log > file
Waqas Khan
fuente
9

Para el registro, ninguna de las respuestas anteriores ayudó excepto una. Para resumir, puede realizar la operación de copia de seguridad --files-from=utilizando:

 rsync -aSvuc `cat rsync-src-files` / mnt / d / rsync_test /

O

rsync -aSvuc --recursive --files-from = rsync-src-files. / mnt / d / rsync_test /

El primer comando se explica por sí mismo, al lado del contenido del archivo rsync-src-filesque detallaré a continuación. Ahora, si desea utilizar la última versión, debe tener en cuenta las siguientes cuatro observaciones:

  1. Tenga en cuenta que es necesario especificar ambos --files-fromy el directorio de origen
  2. Es necesario especificar explícitamente --recursive.
  3. El archivo rsync-src-fileses un archivo creado por el usuario y se colocó dentro del directorio src para esta prueba
  4. La rsyn-src-filescontienen los archivos y carpetas a copiar y que se toman en relación con el directorio de origen. IMPORTANTE: asegúrese de que no haya espacios al final ni líneas en blanco en el archivo. En el siguiente ejemplo, solo hay dos líneas, no tres (descúbrelo por casualidad). El contenido de rsynch-src-fileses:

folderName1
folderName2

KF
fuente
3

Obtuve una tarea similar: rsync todos los archivos modificados después de la fecha dada, pero excluyendo algunos directorios. Era difícil construir un estilo liner todo en uno, así que me sumergí en el problema en piezas más pequeñas. Solución final:

find  ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | egrep -v "/\..|Downloads|FOO" > FileList.txt
rsync -v --files-from=FileList.txt ~/sourceDIR /Destination

Primero utilizo find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS". Intenté agregar regexa la findlínea para excluir los patrones de nombre, sin embargo, mi sabor de Linux (Mint) parece no entender negar regex en find. Intenté varios sabores de expresiones regulares; no funcionan como se desea. Así que termino con una egrep -vopción que excluye el patrón de manera fácil. Mi rsyncno está copiando directorios como /.cache o /.config más algunos otros que nombré explícitamente.

sopel
fuente
1
Creo que se podría utilizar la sustitución de proceso para convertir esto en una bashsola línea:rsync -v --files-from=<(find ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS" | grep -Ev "/\..|Downloads|FOO") ~/sourceDIR /Destination
PHK
2
$ date
  Wed 24 Apr 2019 09:54:53 AM PDT
$ rsync --version
  rsync  version 3.1.3  protocol version 31
  ...

Sintaxis: rsync <file_/_folder_list> <source> <target>

Los nombres de las carpetas (aquí, CON un final /; por ejemplo Cancer - Evolution/) están en un archivo de lista de carpetas (por ejemplo: cm_folder_list_test):

# /mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test
# test file: 2019-04-24
Cancer/
Cancer - Evolution/
Cancer - Genomic Variants/
Cancer - Metastasis (EMT Transition ...)/
Cancer Pathways, Networks/
Catabolism - Autophagy; Phagosomes; Mitophagy/
Catabolism - Lysosomes/

Si no los incluye al final /, se crean las carpetas de destino rsync'd, pero están vacías.

Estos nombres de carpeta se añaden al resto de su ruta ( /home/victoria/Mail/2_RESEARCH - NEWS), proporcionando así la ruta completa de la carpeta a rsync; por ejemplo: /home/victoria/Mail/2_RESEARCH - NEWS/Cancer - Evolution/.

Tenga en cuenta que también debe usar --files-from=..., NO --include-from=...

rsync -aqP --delete --files-from=/mnt/Vancouver/projects/ie/claws/data/cm_folder_list_test "/home/victoria/Mail/2_RESEARCH - NEWS" $IN/

(En mi script BASH, definí la variable de la $INsiguiente manera).

BASEDIR="/mnt/Vancouver/projects/ie/claws"
IN=$BASEDIR/data/test/input

Opciones de rsync utilizadas:

 -a  :   archive: equals -rlptgoD (no -H,-A,-X)
    -r  :   recursive
    -l  :   copy symlinks as symlinks
    -p  :   preserve permissions
    -t  :   preserve modification times 
    -g  :   preserve group 
    -o  :   preserve owner (super-user only) 
    -D  :   same as --devices --specials 
  -q  :   quiet (/server/547106/run-totally-silent-rsync)

  --delete
    This  tells  rsync to delete extraneous files from the RECEIVING SIDE (ones
    that AREN’T ON THE SENDING SIDE), but only for the directories that are
    being synchronized.  You must have asked rsync to send the whole directory
    (e.g.  "dir" or "dir/") without using a wildcard for the directory’s contents
    (e.g. "dir/*") since the wildcard is expanded by the shell and rsync thus
    gets a request to transfer individual files, not the files’ parent directory.
    Files  that  are  excluded  from  the transfer are also excluded from being
    deleted unless you use the --delete-excluded option or mark the rules as
    only matching on the sending side (see the include/exclude modifiers in the
    FILTER RULES section).  ...
Victoria Stuart
fuente
1

Esta respuesta no es la respuesta directa a la pregunta. Pero debería ayudarlo a descubrir qué solución se adapta mejor a su problema.

Al analizar el problema debes activar la opción de depuración -vv

Luego, rsync generará qué archivos se incluyen o excluyen mediante qué patrón:

building file list ... 
[sender] hiding file FILE1 because of pattern FILE1*
[sender] showing file FILE2 because of pattern *
Matthias M
fuente
0

Ninguna de estas respuestas funcionó para mí, cuando todo lo que tenía era una lista de directorios . ¡Entonces me topé con la solución! Usted tiene que agregar -ra --files-fromporque -ano va a ser recursiva en este escenario (que sabía ?!).

rsync -aruRP --files-from=directory.list . ../new/location
Theodore R. Smith
fuente
Si enumera "dir" en el archivo, entonces debe especificar -r / —recursive; si en la lista "dir /" no lo hace.
lbutlr