rsync copia apenas certos tipos de arquivos usando a opção de inclusão
110
Eu uso o seguinte script bash para copiar apenas arquivos de certa extensão (neste caso * .sh), no entanto, ele ainda copia todos os arquivos. o que há de errado?
de = $ 1
para = $ 2
rsync -zarv --include = "*. sh" $ de $ a
Embora não seja estritamente relacionado, sugiro citar $ from / $ to. Não fazer isso pode gerar resultados inesperados se os argumentos posicionais 1/2 incluírem espaços.
Kjetil Joergensen de
você entendeu por que seu comando simplesmente não funcionava?
Charlie Parker
@CharlieParker: Você tem que usar rsync, isso pode muito bem ser conseguido com os internos do shell?
Inian
O que essa pergunta e suas respostas também carecem é como criar o comando se eu tiver diretórios recursivos para os quais desejo enviar apenas um tipo de arquivo. Parece que só faz isso para o diretório de destino ...
Charlie Parker
Respostas:
198
Acho que --includeé usado para incluir um subconjunto de arquivos que são excluídos por --exclude, em vez de incluir apenas esses arquivos. Em outras palavras: você tem que pensar em incluir significado , não excluir .
Adicionar o -msinalizador evitará a criação de estruturas de diretório vazias no destino. Testado na versão 3.1.2.
Portanto, se quisermos apenas arquivos * .sh, temos que excluir todos os arquivos --exclude="*", incluir todos os diretórios --include="*/"e incluir todos os arquivos * .sh --include="*.sh".
Você pode encontrar alguns bons exemplos na seção Regras de padrão de inclusão / exclusão da página do manual
Embora ele forneça a você todos os subdiretórios, se houver algum arquivo .sh nos subdiretórios que deseja fazer rsync, é provável que você queira usar --include = "* /" também.
Kjetil Joergensen de
50
Eu tentei isso no rsync versão 3.0.7, que peguei há muito tempo no macports, e não funcionou com essa ordem de inclusões / exclusões. Isto é o que eu acabei com que funcionou para mim (adaptado para OP): rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille
3
Tentei com o rsync 3.0.9 e não funcionou. Bijou está certo, a ordem não é adequada (primeiro, --include=\*.shentão --exclude=\*)
TrueY
3
Observe que você sempre pode clicar em editar e sugerir uma edição para a resposta :)
Achal Dave
2
Não funciona com o seu pedido de inclui / exclui, mas funciona com o pedido sugerido por Bijou Trouvaille
John Smith Opcional
56
A resposta de @chepner irá copiar todos os subdiretórios independentemente do fato de conterem o arquivo ou não. Se você precisar excluir os subdiretórios que não contêm o arquivo e ainda retêm a estrutura do diretório, use
Este foi um requisito para mim: "Se você precisar excluir os subdiretórios que não contêm o arquivo e ainda reter a estrutura do diretório" +1
Juuso Ohtonen
1
Não entendo como você sabia qual era a ordem dos --includes?
Charlie Parker
1
Como criar o comando se tenho diretórios recursivos para os quais desejo enviar apenas um tipo de arquivo. Parece que só faz isso para o diretório de destino.
Charlie Parker de
15
Mais uma adição: se você precisar sincronizar arquivos por suas extensões em um único diretório (sem recursão), você deve usar uma construção como esta:
como você sabia qual deveria ser a ordem das bandeiras e o que elas deveriam incluir?
Charlie Parker
1
@CharlieParker, porque o rsync usa o includee as excludeopções na ordem que eles foram especificados. Além disso, ele pára em um primeiro correspondido. Portanto, se especificarmos --exclude '*'no primeiro lugar neste exemplo, o rsync não fará nada. Veja o homem para mais explicações.
Serge Roussak de
você pode me explicar o que cada bandeira está fazendo? O primeiro sinalizador -- include './' indica incluir tudo no caminho do diretório de origem? Então o próximo `--include '.ext'` inclui o arquivo específico no caminho de origem nomeado .exte então o exclude diz não enviar mais nada --exclude '*'? Isso é correto?
Charlie Parker
1
Como criar o comando se tenho diretórios recursivos para os quais desejo enviar apenas um tipo de arquivo. Parece que só faz isso para o diretório de destino.
Charlie Parker
1
Obrigado por isso! Precisa --include '*.ext'e não--include '.ext'
gbyte
13
Aqui está a parte importante da página de manual:
Conforme a lista de arquivos / diretórios a serem transferidos é construída, o rsync verifica cada nome a ser transferido em relação à lista de padrões de inclusão / exclusão, por sua vez, e o primeiro padrão correspondente é acionado: se for um padrão de exclusão, então esse arquivo é pulado; se for um padrão de inclusão, o nome do arquivo não será ignorado; se nenhum padrão correspondente for encontrado, o nome do arquivo não será ignorado.
Para resumir:
Não corresponder a nenhum padrão significa que um arquivo será copiado!
O algoritmo fecha assim que qualquer padrão coincide
Além disso, algo que termina com uma barra está combinando com os diretórios (como find -type d faria).
Muito obrigado por explicar o que está acontecendo. Agora há uma chance muito melhor de eu não esquecer o comando.
MohamedEzz
3
'' O algoritmo é encerrado assim que qualquer padrão corresponde " - esta é a chave, e nenhuma das respostas com classificação mais alta o explica de forma tão clara e direta como você fez aqui. Claro que isso está na página de manual em algum lugar, e se eu leria tudo com cuidado, eu teria visto. Ainda assim, obrigado.
TheDudeAbides
0
Se alguém procurar por isso ... Queria rsync apenas arquivos e pastas específicos e consegui fazer com este comando: rsync --include-from=rsync-files
Escrevi esta função útil e coloquei em meus scripts bash ou ~/.bash_aliases. Sincronização testada localmente no Linux com bash e awkinstalada. Funciona
selrsync(){# selective rsync to sync only certain filetypes;# based on: https://stackoverflow.com/a/11111793/588867# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift;#accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk -F',' \
'BEGIN{OFS=" ";}
{
for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
}')
restargs="$@"
echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*""$restargs"eval rsync -avz --prune-empty-dirs --include="*/""$includes"--exclude="*" $restargs
}
Avantages:
curto, prático e extensível quando se deseja adicionar mais argumentos (ou seja --dry-run).
rsync
, isso pode muito bem ser conseguido com os internos do shell?Respostas:
Acho que
--include
é usado para incluir um subconjunto de arquivos que são excluídos por--exclude
, em vez de incluir apenas esses arquivos. Em outras palavras: você tem que pensar em incluir significado , não excluir .Em vez disso, tente:
Para rsync versão 3.0.6 ou superior, o pedido precisa ser modificado da seguinte forma (veja os comentários):
Adicionar o
-m
sinalizador evitará a criação de estruturas de diretório vazias no destino. Testado na versão 3.1.2.Portanto, se quisermos apenas arquivos * .sh, temos que excluir todos os arquivos
--exclude="*"
, incluir todos os diretórios--include="*/"
e incluir todos os arquivos * .sh--include="*.sh"
.Você pode encontrar alguns bons exemplos na seção Regras de padrão de inclusão / exclusão da página do manual
fonte
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
.--include=\*.sh
então--exclude=\*
)A resposta de @chepner irá copiar todos os subdiretórios independentemente do fato de conterem o arquivo ou não. Se você precisar excluir os subdiretórios que não contêm o arquivo e ainda retêm a estrutura do diretório, use
fonte
Mais uma adição: se você precisar sincronizar arquivos por suas extensões em um único diretório (sem recursão), você deve usar uma construção como esta:
Preste atenção ao ponto no primeiro
--include
.--no-r
não funciona nesta construção.EDITAR:
Obrigado a gbyte.co pelo valioso comentário!
fonte
include
e asexclude
opções na ordem que eles foram especificados. Além disso, ele pára em um primeiro correspondido. Portanto, se especificarmos--exclude '*'
no primeiro lugar neste exemplo, o rsync não fará nada. Veja o homem para mais explicações.-- include './'
indica incluir tudo no caminho do diretório de origem? Então o próximo `--include '.ext'` inclui o arquivo específico no caminho de origem nomeado.ext
e então o exclude diz não enviar mais nada--exclude '*'
? Isso é correto?--include '*.ext'
e não--include '.ext'
Aqui está a parte importante da página de manual:
Para resumir:
Além disso, algo que termina com uma barra está combinando com os diretórios (como
find -type d
faria).Vamos separar essa resposta de cima.
.sh
arquivoFinalmente, o
--prune-empty-directories
impede que a primeira regra crie diretórios vazios em todos os lugares.fonte
Se alguém procurar por isso ... Queria rsync apenas arquivos e pastas específicos e consegui fazer com este comando:
rsync --include-from=rsync-files
Com arquivos rsync:
fonte
Escrevi esta função útil e coloquei em meus scripts bash ou
~/.bash_aliases
. Sincronização testada localmente no Linux com bash eawk
instalada. FuncionaAvantages:
curto, prático e extensível quando se deseja adicionar mais argumentos (ou seja
--dry-run
).Exemplo:
fonte