rsync uma lista de diretórios com caminho absoluto no arquivo de texto

9

Eu tenho um arquivo de texto que contém uma lista de diretórios com seu caminho absoluto

$ cat DirectoriesToCopy.txt

/data/Dir1
/data/Dir2

Eu quero usar o rsync para copiar todos esses diretórios, preservando seu caminho absoluto para outro local.

Eu tentei o seguinte comando rsync, mas não funciona

rsync -avr --include-from=DirectoriesToCopy.txt --exclude='*/' --exclude='/*'  /  /media/MyDestination/

o que há de errado aqui?

indiajoe
fonte
Deseja transferir /data/Dir1e /data/Dir2incluir o conteúdo para /media/MyDestination/Dir1e /media/MyDestination/Dir2? Ou você deseja incluir a /datapeça? Qual é o tamanho dessa lista? É muito grande para simplesmente listar essas entradas na linha de comando? De qualquer forma, suas --excludedeclarações impedem a recursão.
amigos estão dizendo sobre wurtel
Eu quero transferir todos os arquivos dentro desses diretórios também. Existem muitos arquivos nesse diretório, então eu gostaria de evitar a criação de outro arquivo de texto com todos os nomes de arquivos.
indiajoe
Eu gostaria de manter o meu caminho completo como /media/MyDestination/data/Dir2/. Eu adicionei o --exclude para impedir que outros diretórios e arquivos sejam copiados.
indiajoe
Nos casos em que a lista de diretórios não é muito grande, acho que a opção a seguir é mais fácilrsync -av $(cat DirectotiesToCopy.txt) /media/MyDestination/
indiajoe:

Respostas:

6

Use o seguinte comando:

rsync -av --include-from=DirectoriesToCopy.txt --include /data/ --exclude='/data/*' --exclude='/*/' / /media/MyDestination/

Você precisa incluir / data / explicitamente, também pode ter adicionado isso à lista no arquivo. Exclua todos os outros diretórios (a ordem é importante com inclusões / exclusões).

Observe que seu uso -rfoi redundante, pois está incluído no -a.

EDIT: Você também pode obter o mesmo resultado com:

rsync -av --relative /data/Dir1 /data/Dir2 /media/MyDestination/

Não é o rsync que está forçando você a fazer coisas difíceis apenas para copiar alguns diretórios, mas oferece várias maneiras de fazer a mesma coisa; em alguns casos, a maneira de incluir / excluir pode ser mais adequada, aqui eu faria a coisa - relativa acima (sem --relativevocê terminar com /media/MyDestination/Dir1e /media/MyDestination/Dir2, com --relativetodo o caminho de origem sendo copiado para o destino).

Wurtel
fonte
Obrigado que trabalhou. Estou um pouco surpreso que seja necessário definir uma sequência cuidadosa de filtros para simplesmente copiar uma lista de diretórios usando o rsync. Por exemplo, se minha lista de diretórios não estava em um diretório / dados comum, mas estava espalhada por vários locais, os filtros a serem definidos se tornam bastante complicados.
indiajoe
Veja minha edição na minha resposta.
wurtel
Obrigado. Portanto, se minha lista de diretórios não for muito grande, eu poderia usar o sinalizador --relative, como mostrado abaixo. rsync -av --relative $(cat DirectotiesToCopy.txt) /media/MyDestination/
precisa
Sim; tenha em mente --relativeé apenas outra opção.
wurtel
7

Eu quero usar o rsync para copiar todos esses diretórios [de uma lista] preservando seu caminho absoluto para outro local

Não use --includeou --filtervariações, como que vai coisas simplesmente Confuse. Em vez disso, use --files-from=_filename_. (Se fizer isso, faça muitos testes.)

  1. Crie a lista de diretórios em um arquivo, um diretório / arquivo por linha.

  2. Use rsync's --files-from=com o arquivo acima.

  3. Use --relative/ -Roption para garantir que os nomes dos caminhos de origem sejam copiados no final do destino.

  4. Mesmo se você tiver a -aopção, inclua também -r. Na página do manual:

    Nos dois casos, se a opção -r estiver ativada, a hierarquia inteira desse diretório também será transferida (lembre-se de que -r precisa ser especificado explicitamente com --files-from, pois não está implícito em -a).

Comando completo:

rsync ${DEBUG:+-nv} -arR --files-from=<list_of_files.txt> <top-level-dir>  <target-dir>

(os arquivos em list_of_files.txt devem ser relativos ou encontrados no diretório de nível superior )

(se DEBUG estiver definido, o rsync simplesmente imprime o que pode ter sido copiado.)

Otheus
fonte
1
Era disso que eu precisava! No entanto, "--include-from" deve ser "--files-from". Também usei "--list-only" para ver uma prévia do que o RSYNC fará antes de deixá-lo funcionar.
Adambean
1
Obrigado, atualizei a resposta. --include-fromtambém funcionará, mas o que eu disse sobre isso -ré amplamente irrelevante.
Otheus
2

O manual do rsync alerta sobre esse cenário (seção “Incluir / excluir regras de padrão”):

isso não vai funcionar:

+ /some/path/this-file-will-not-be-found
+ /file-is-included
- *

Isso falha porque o diretório pai "some"é excluído pela '*'regra, portanto, o rsync nunca visita nenhum arquivo nos diretórios "some"ou "some/path". Uma solução é solicitar que todos os diretórios na hierarquia sejam incluídos usando uma única regra: "+ */"(coloque-a em algum lugar antes da "- *"regra) e talvez use a --prune-empty-dirsopção Outra solução é adicionar regras de inclusão específicas para todos os diretórios pai que precisam ser visitados. Por exemplo, este conjunto de regras funciona bem:

+ /some/
+ /some/path/
+ /some/path/this-file-is-found
+ /file-also-included
- *

No seu caso, acho que a abordagem mais simples seria a de pré-processar a lista de diretórios para incluir para que sempre que você incluir /path/to/foo, você também incluir todos os diretórios pai ( /path/to, /path, /), e também incluem subdiretórios dos diretórios originais ( /path/to/foo/***), e depois de tudo isso tem uma regra que exclui tudo que não foi listado anteriormente ( *).

<DirectoriesToCopy.txt awk '
    {print "+ " $0 "/***"; while (sub(/\/+[^\/]+\/*$/, "/")) print "+ " $0}
    END {print "- *"}
' >rsync-rules.txt
rsync -avr --include-from=rsync-rules.txt  /  /media/MyDestination/
Gilles 'SO- parar de ser mau'
fonte
Obrigado pela explicação detalhada e script para criar o arquivo de regras. Eu entendo o problema agora. Eu ainda acho que seria bom para o rsync ter uma opção como --dirs-from = DirectoriesToCopy.txt como um atalho para todos os filtros complicados.
indiajoe