scp sem substituir arquivos existentes no destino

158

Como copiar um diretório inteiro para um diretório com o mesmo nome sem substituir o conteúdo no diretório de destino? (em vez disso, eu gostaria de adicionar ao conteúdo da pasta de destino)

Daniel Böhmer
fonte
Sim, é irritante quando um programa / utilitário útil não possui essa opção "se ao menos pudesse ..."! Neste caso "--noclobber"!
7278 MikeW

Respostas:

139

Use rsynce passe -use desejar atualizar apenas os arquivos mais recentes no diretório original ou --ignore-existingignorar todos os arquivos que já existem no destino.

rsync -au /local/directory/ host:/remote/directory/
rsync -a --ignore-existing /local/directory/ host:/remote/directory/

(Observe o /lado da fonte: sem ele rsynccriaria /remote/directory/directory.)

Gilles
fonte
@Anton Não entendo o seu comentário e não vejo uma resposta ou comentário de chandra. --ignore-existingadiciona sem substituir, que perda de dados você vê?
Gilles
Desculpe, olhei apenas para o seu primeiro exemplo, onde é possível ter perda de dados (e IMHO não é o que o OP solicitou), se você incluir --ignore-a perda de dados existente não deve acontecer.
Anthon
Isso não ajuda se o sistema remoto não estiver rsyncdisponível com facilidade .... (Como Win32-OpenSSH)
Gert van den Berg
@GertvandenBerg rsync é muito fácil de instalar no Windows, não é mais difícil que o SSH.
Gilles
@Gilles: Verdade, mas todas as opções parecem envolver DLLs Cygwin ... (O estado atual da porta MS do OpenSSH é tal que ativar a compactação no scp é suficiente para interromper o SCP ...) (Tornar o rsync funcional no Win32 -OpenSSH também parece não trivial - esperamos que melhora ao longo do tempo) (Solaris 10 é outro exemplo, onde um pacote e de terceiros --rsync-pathé necessária)
Gert van den Berg,
82

O scp substituirá os arquivos se você tiver permissões de gravação para eles.

Em outras palavras: você pode scpefetivamente pular esses arquivos removendo temporariamente as permissões de gravação neles (se você é o proprietário dos arquivos).

Reimund
fonte
5
Obrigado por isso. Era exatamente o truque que eu estava procurando.
Saccharine
certifique-se de copiar os arquivos novamente e adicione um * para fazer isso. Exemploscp -r [email protected]:/location/of/files/* /local/location/
Rick
1
encontrar . -type f -exec raiz do chown: root {} \;
ling
1
No caso incomum de que apenas alguns dos arquivos no diretório devem ser substituídos (se não "protegidos") e as permissões de arquivo não são uniformes entre os arquivos, esta solução pode não funcionar. Caso contrário, é bastante simples e eficaz.
Sancho.s
Para fazer isso no Windows selecionar todos os arquivos, clique direito -> Propriedades -> somente leitura
benjammin
12

Você pode copiar apenas novos arquivos por data. Usarfind

scp  `find /data/*.gz -type f -mtime +7` USER@SERVER:/backup/
Naks
fonte
o que significa +7?
Francis Kim
@FrancisKim significa modificado 7 dias atrás. Portanto, essa consulta seleciona qualquer arquivo * .gz modificado nos últimos 7 dias
Vadim Eremeev
4
+7 na verdade não implica mais de 7 dias atrás?
Jeff H.
1
Sim, significa "mais de 7 dias atrás". Não faço ideia quem votou nisso.
Stefan Reich
9

Se você pode tornar o conteúdo do arquivo de destino somente leitura:

find . -type f -exec chmod a-w '{}' \;

antes de executar scp(ele irá reclamar e pular os arquivos existentes).

E altere-os novamente depois ( chmod +wpara obter um valor baseado em umask). Se nem todos os arquivos tiverem permissão de gravação de acordo com o umask, você precisará armazenar as permissões para poder restaurá-las.

(A resposta de Gilles substitui os arquivos existentes, se eles forem mais novos localmente, perdi dados valiosos dessa maneira. Não entendo por que essa resposta errada e prejudicial tem tantos votos positivos).

Mohad
fonte
2
Não entendi: como rsync --ignore-existingvocê perdeu dados?
Gilles
4
Eu tenho o erro find: missing argument to '-exec'de utilizar este comando, e em vez teve de usar: find . -type f -exec chmod a-w {} \;. Meu linux está ruim, sim.
Wpearse
Esta é uma resposta melhor e mais segura. O comando correto para alterar a permissão é como @wpearse mencionado:find . -type f -exec chmod a-w {} \;
Amir
6

Eu tinha uma tarefa semelhante, no meu caso eu não poderia usar rsync, csyncou FUSE porque meu armazenamento tem apenas SFTP. rsyncnão foi possível alterar a data e a hora do arquivo, alguns outros utilitários (como csync) me mostraram outros erros: " Não foi possível criar o arquivo temporário A inclinação do relógio foi detectada ".

Se você tiver acesso ao servidor de armazenamento - basta instalar openssh-serverou iniciar rsynccomo um daemon aqui.

No meu caso - não pude fazer isso e a solução foi: lftp . lftpO uso da sincronização está abaixo:

lftp -c "open -u login,password sftp://sft.domain.tld/; \
    mirror -c --verbose=9 -e -R -L /srs/folder /rem/folder"

/src/folder- é a pasta no meu PC, /rem/folder- é sftp://sft.domain.tld/rem/folder.

Você pode encontrar as páginas de manual no link: http://lftp.yar.ru/lftp-man.html

negrito
fonte
6

Para copiar um monte de arquivos, é mais rápido tar. Ao usar -k, você também evita que o tar substitua arquivos ao descompactá-lo no sistema de destino.

tar -c <source-dir> | ssh <name>@<host> 'tar -kxzf - -C <target-dir>' 
Huembi
fonte
1
Faz uma conexão remota. Primeiro, é a fonte do tar, canaliza na conexão ssh e descompacta no sistema remoto.
precisa saber é o seguinte
-1

scpsobrescreve arquivos e não há como impedir que isso seja feito, mas você pode copiar as coisas do caminho, fazer o scp e depois copiar os arquivos existentes novamente. Exemplos:

  1. Copie todos os arquivos existentes do caminho

    mkdir original_files ; cp -r * original_files/
    
  2. Copie tudo usando scp

    scp -r user@server:dir/* ./
    
  3. Copie os arquivos originais sobre qualquer coisa que o scp tenha escrito:

    cp -r original_files/* ./
    
A.Badger
fonte
3
Esse método não ajuda quando você está tentando extrair arquivos de um controle remoto e continuar de onde parou. Ou seja, se o objetivo é economizar tempo.
Oliver Williams
-1

Outra maneira de conseguir isso é fazer um lsna pasta de destino:

Na pasta de destino remoto:

ls | awk '{print "mv " $1 " ../copied_data/"}' > mv_copied_data
scp mv_copied_data [email protected]:/path/to/source/folder

Na fonte:

cd /path/to/source/folder
chmod 777 mv_copied_data
./mv_copied_data

No destino:

scp -r [email protected]:/path/to/source/folder /path/to/destination/foldeer
sameer gurjar
fonte
Por favor, não faça isso. 1. Não analise ls . 2. A resposta é perigosa se algum nome de arquivo contiver - >nova linha de espaço ou outros caracteres especiais. 3. Codifique um loop for em um script python. Gerar um programa em tempo de execução é difícil e complicado (mesmo quando feito por programadores profissionais), por várias razões. Gerar um script de shell é ainda pior - uma péssima idéia.
ignis 01/06