Como fazer o rsync apenas para uma lista específica de arquivos?

93

Tenho cerca de 50 arquivos em vários subdiretórios que gostaria de enviar para um servidor remoto. Achei que o rsync seria capaz de fazer isso por mim usando a opção --include-from. Sem a opção --exclude = "*", todos os arquivos no diretório estão sendo sincronizados, com a opção, nenhum arquivo está.

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

Estou executando-o como seco inicialmente e 0.0.0.0 foi obviamente substituído pelo IP do servidor remoto. O conteúdo de rsync_include.txt é uma nova lista separada por linha de caminhos relativos para os arquivos que desejo enviar.

Existe uma maneira melhor de fazer isso que está me escapando na segunda-feira de manhã?

Dan Steele
fonte

Respostas:

3

Edit: A resposta de Josip Rodin abaixo é melhor. Por favor, use esse!

Talvez seja mais fácil se você estiver procurando por uma lista específica de arquivos, colocando-os diretamente na linha de comando:

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

Isso pressupõe, no entanto, que sua lista não é tão longa que o comprimento da linha de comando será um problema e que o rsync_include.txtarquivo contém apenas caminhos reais (ou seja, sem comentários e sem regexps).

Wes Hardaker
fonte
9
Infelizmente, isso não funciona com uma lista grande ou com arquivos com espaços no nome.
Wes Modes
3
[Lista de argumentos muito longa]
Dankó Dávid
Por padrão, xargs acrescenta argumentos de stdin ao final da linha de comando. Isso não funciona porque o rsync precisa que o último argumento seja o destino. Algumas versões do xargs podem opcionalmente inserir argumentos no meio da linha de comando. Isso deve funcionar, desde que você não se importe que o rsync possa ser executado mais de uma vez quando a lista de arquivos for longa. Em qualquer caso, rsync --files-fromé provavelmente uma solução mais fácil e confiável :)
Lassi
Wes Hardaker: Sua edição e referência à "resposta de Josip Rodin" realmente se referem à resposta @atp que Rodin editou?
Seamus
228

Existe uma bandeira --files-fromque faz exatamente o que você deseja. De man rsync:

--files-from=FILE

O uso desta opção permite que você especifique a lista exata de arquivos a serem transferidos (conforme lidos no ARQUIVO especificado ou - para entrada padrão). Ele também ajusta o comportamento padrão do rsync para facilitar a transferência apenas dos arquivos e diretórios especificados:

  • A opção --relative (-R) está implícita, o que preserva as informações de caminho que são especificadas para cada item no arquivo (use --no-relative ou --no-R se você quiser desligar isso).

  • A opção --dirs (-d) está implícita, o que criará diretórios especificados na lista no destino ao invés de ignorá-los ruidosamente (use --no-dirs ou --no-d se você quiser desligá-los).

  • O comportamento da opção --archive (-a) não implica --recursive (-r), então especifique-o explicitamente, se você quiser.

  • Estes efeitos colaterais mudam o estado padrão do rsync, então a posição da opção --files-from na linha de comando não tem relação com a forma como as outras opções são analisadas (por exemplo, -a funciona da mesma forma antes ou depois de --files- de, assim como --no-R e todas as outras opções).

Os nomes de arquivo que são lidos do ARQUIVO são todos relativos ao diretório de origem - quaisquer barras iniciais são removidas e nenhuma referência ".." tem permissão para ir além do diretório de origem. Por exemplo, use este comando:

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

Se / tmp / foo contém a string "bin" (ou mesmo "/ bin"), o diretório / usr / bin será criado como / backup / bin no host remoto. Se ele contiver "bin /" (observe a barra final), o conteúdo imediato do diretório também será enviado (sem a necessidade de ser mencionado explicitamente no arquivo - isso começou na versão 2.6.4). Em ambos os casos, se a opção -r fosse habilitada, toda a hierarquia do dir também seria transferida (tenha em mente que -r precisa ser especificado explicitamente com --files-from, uma vez que não está implícito em -a). Observe também que o efeito da opção (habilitada por padrão) --relative é duplicar apenas as informações do caminho que são lidas do arquivo - não força a duplicação do caminho da especificação da fonte (/ usr neste caso) .

Além disso, o arquivo --files-from pode ser lido do host remoto em vez do host local se você especificar um "host:" na frente do arquivo (o host deve corresponder a uma extremidade da transferência). Como um atalho, você pode especificar apenas um prefixo de ":" para significar "usar o fim remoto da transferência". Por exemplo:

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

Isso copiaria todos os arquivos especificados no arquivo / path / file-list que estava localizado no host "src" remoto.

Se as opções --iconv e --protect-args forem especificadas e os nomes de arquivos --files-from estiverem sendo enviados de um host para outro, os nomes dos arquivos serão traduzidos do conjunto de caracteres do host de envio para o conjunto de caracteres do host de recebimento.

NOTA: classificar a lista de arquivos na entrada --files-from ajuda o rsync a ser mais eficiente, pois evitará revisitar os elementos do caminho que são compartilhados entre as entradas adjacentes. Se a entrada não for classificada, alguns elementos de caminho (diretórios implícitos) podem acabar sendo verificados várias vezes e o rsync acabará por desduplicá-los depois de serem transformados em elementos de lista de arquivos.

atp
fonte
22
Observe que você ainda precisa especificar o diretório onde os arquivos listados estão localizados, por exemplo: rsync -av --files-from=file-list . target/para copiar os arquivos do diretório atual.
Nicolas Mattia
7
Sim, e reiterar: The filenames that are read from the FILE are all relative to the source dir.
atp
Ah, perdi isso, desculpe!
Nicolas Mattia
1
se o arquivo files-from tiver algo que comece com ..rsync, parece ignorar o ..erro que me dá como rsync: link_stat "/home/michael/test/subdir/test.txt" failed: No such file or directory(neste caso, executando a partir do diretório "test" e tentando especificar "../subdir/test.txt" que existe.
Michael
O --files-fromargumento pode ser combinado com uma lista explícita de inclusões e exclusões, e os arquivos da lista adicionados --files-fromsubstituirão as regras de exclusão existentes, de modo que sejam incluídos se aparecerem no arquivo?
highsciguy
12

--files-from=O parâmetro precisa de uma barra final se você quiser manter o caminho absoluto intacto. Portanto, seu comando seria algo como abaixo:

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

Isso pode ser feito como se houvesse um grande número de arquivos e você deseja copiar todos os arquivos para o caminho x. Assim, você encontraria os arquivos e geraria a saída para um arquivo como abaixo:

find /var/* -name *.log > file
Waqas Khan
fonte
8

Para que fique registrado, nenhuma das respostas acima ajudou, exceto uma. Para resumir, você pode fazer a operação de backup --files-from=usando:

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

OU

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

O primeiro comando é autoexplicativo, ao lado do conteúdo do arquivo rsync-src-filesque elaborarei a seguir. Agora, se você quiser usar a última versão, você precisa ter em mente as seguintes quatro observações:

  1. Observe que é necessário especificar ambos --files-frome o diretório de origem
  2. É preciso especificar explicitamente --recursive.
  3. O arquivo rsync-src-filesé um arquivo criado pelo usuário e foi colocado no diretório src para este teste
  4. Eles rsyn-src-filescontêm os arquivos e pastas a serem copiados e são levados em relação ao diretório de origem. IMPORTANTE: Certifique-se de que não haja espaços à direita ou linhas em branco no arquivo. No exemplo abaixo, existem apenas duas linhas, não três (descubra por acaso). Conteúdo de rsynch-src-filesé:

folderName1
folderName2

KF
fonte
3

Recebi uma tarefa semelhante: fazer rsync para todos os arquivos modificados após determinada data, mas excluindo alguns diretórios. Era difícil construir um estilo all-in-one de revestimento, então mergulhei o problema em pedaços menores. Solução 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

Primeiro eu uso find -L ~/sourceDIR -type f -newermt "DD MMM YYYY HH:MM:SS". Tentei adicionar regexà findlinha para excluir padrões de nome, porém meu sabor de Linux (Mint) parece não entender negar regex em find. Número experimentado de sabores de regex - não funciona como desejado. Então eu acabo com egrep -v- opção que exclui o padrão de maneira fácil. Meu rsyncnão está copiando diretórios como /.cache ou /.config além de alguns outros que nomeei explicitamente.

sopel
fonte
1
Eu acredito que você poderia usar a substituição de processo para transformar isso em uma linha bashúnica: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
  ...

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

Os nomes das pastas (aqui, COM um final /; por exemplo Cancer - Evolution/) estão em um arquivo de lista de pastas (por exemplo: 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/

Se você não incluir aqueles à direita /, as pastas de destino rsync serão criadas, mas estarão vazias.

Esses nomes de pasta são anexados ao resto de seu caminho ( /home/victoria/Mail/2_RESEARCH - NEWS), fornecendo assim o caminho de pasta completo para rsync; por exemplo: /home/victoria/Mail/2_RESEARCH - NEWS/Cancer - Evolution/.

Observe que você também precisa usar --files-from=..., NÃO --include-from=...

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

(No meu script BASH, defini a variável da $INseguinte forma.)

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

Opções de rsync usadas:

 -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
fonte
1

Esta resposta não é a resposta direta para a pergunta. Mas deve ajudá-lo a descobrir qual solução se encaixa melhor para o seu problema.

Ao analisar o problema você deve ativar a opção de depuração -vv

Em seguida, o rsync irá mostrar quais arquivos são incluídos ou excluídos por qual padrão:

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

Nenhuma dessas respostas funcionou para mim, quando tudo que eu tinha era uma lista de diretórios . Então eu tropecei na solução! Você tem que adicionar -ra --files-fromcausa -anão será recursiva neste cenário (que sabia ?!).

rsync -aruRP --files-from=directory.list . ../new/location
Theodore R. Smith
fonte
Se você listar “dir” no arquivo, será necessário especificar -r / —recursive; se você listar “dir /“, não.
lbutlr