scp sin reemplazar los archivos existentes en el destino


158

¿Cómo copio un directorio completo en un directorio con el mismo nombre sin reemplazar el contenido en el directorio de destino? (en cambio, me gustaría agregar al contenido de la carpeta de destino)


Sí, es molesto cuando un programa / utilidad útil no tiene esa opción "¡si tan solo pudiera ..."! En este caso "--noclobber"!
MikeW

Respuestas:


140

Use rsyncy pase -usi solo desea actualizar los archivos que son más nuevos en el directorio original, o --ignore-existingpara omitir todos los archivos que ya existen en el destino.

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

(Tenga /en cuenta el lado de la fuente: sin que rsyncse crearía /remote/directory/directory).


@Anthon No entiendo tu comentario y no veo una respuesta o comentario de Chandra. --ignore-existingagrega sin reemplazar, ¿qué pérdida de datos ves?
Gilles

Lo siento, solo miré su primer ejemplo que es donde puede tener pérdida de datos (y en mi humilde opinión no es lo que solicitó el OP), si incluye --no ignorar la pérdida de datos existente no debería suceder.
Anthon

Esto no ayuda si el sistema remoto no tiene rsyncfácilmente disponible ... (Como Win32-OpenSSH)
Gert van den Berg

@GertvandenBerg rsync es bastante fácil de instalar en Windows, no más difícil que SSH.
Gilles

@Gilles: Cierto, pero todas las opciones parecen involucrar archivos DLL de Cygwin ... (El estado actual del puerto MS de OpenSSH es tal que habilitar la compresión en scp es suficiente para romper SCP ...) (Hacer que rsync funcione sobre Win32 -OpenSSH también parece no trivial, es de esperar que mejore con el tiempo) (Solaris 10 es el otro ejemplo, donde --rsync-pathse necesita un paquete de terceros )
Gert van den Berg

82

scp sobrescribirá los archivos si tiene permisos de escritura.

En otras palabras: puede scpomitir eficazmente dichos archivos eliminando temporalmente los permisos de escritura (si es el propietario de los archivos).


55
Gracias por esto. Fue exactamente el truco que estaba buscando.
sacarina

asegúrese de copiar los archivos de nuevo, agregue un * para hacerlo. Ejemploscp -r user@server.com:/location/of/files/* /local/location/
Rick

1
encontrar . -type f -exec chown root: root {} \;
ling

1
En el caso poco común de que se espera que solo se sobrescriban algunos de los archivos del directorio (si no están "protegidos") y que los permisos de los archivos no son uniformes en todos los archivos, es posible que esta solución no funcione. De lo contrario, es bastante simple y efectivo.
sancho.s

Para hacer esto en Windows, seleccione todos los archivos, haga clic derecho -> propiedades -> solo lectura
BenJammin

12

Puede copiar solo archivos nuevos por fecha. Utilizarfind

scp  `find /data/*.gz -type f -mtime +7` USER@SERVER:/backup/

¿Qué significa +7?
Francis Kim

@FrancisKim significa modificado hace 7 días. Entonces, esta consulta selecciona cualquier archivo * .gz modificado en los últimos 7 días
Vadim Eremeev

44
¿No implica +7 realmente hace más de 7 días?
Jeff H.

1
Sí, significa "hace más de 7 días". No tengo idea de quién votó por esto.
Stefan Reich

9

Si puede hacer que el contenido del archivo de destino sea de solo lectura:

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

antes de ejecutar scp(se quejará y omitirá los archivos existentes).

Y cámbielos nuevamente después ( chmod +wpara obtener un valor basado en umask). Si no todos los archivos tienen permiso de escritura de acuerdo con su umask, de alguna manera tendría que almacenar los permisos para poder restaurarlos.

(La respuesta de Gilles sobrescribe los archivos existentes si localmente son más nuevos, perdí datos valiosos de esa manera. No entiendo por qué esa respuesta incorrecta y dañina tiene tantos votos positivos).


2
No lo entiendo: ¿cómo te hizo rsync --ignore-existingperder datos?
Gilles

44
Tengo el error find: missing argument to '-exec'de utilizar este comando, y en su lugar tuvo que usar: find . -type f -exec chmod a-w {} \;. Mi Linux es malo, mmm.
wpearse

Esta es una respuesta mejor y más segura. El comando correcto para cambiar el permiso es como @wpearse mencionó:find . -type f -exec chmod a-w {} \;
Amir

6

Tenía una tarea similar, en mi caso no podía usar rsync, csynco porque mi fusible de almacenamiento sólo tiene SFTP. rsyncno se pudo cambiar la fecha y la hora del archivo, algunas otras utilidades (como csync) me mostraron otros errores: " No se puede crear el archivo temporal Se detectó una distorsión del reloj ".

Si tiene acceso al servidor de almacenamiento, simplemente instale openssh-servero inicie rsynccomo demonio aquí.

En mi caso, no pude hacer esto y la solución fue: lftp . lftpEl uso de la sincronización está a continuación:

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

/src/folder- es la carpeta en mi PC, /rem/folder- es sftp://sft.domain.tld/rem/folder.

Puede encontrar páginas de manual en el enlace: http://lftp.yar.ru/lftp-man.html


6

Para copiar una gran cantidad de archivos, es más rápido manipularlos. Al usar -k también evita que tar sobrescriba los archivos al desempaquetarlos en el sistema de destino.

tar -c <source-dir> | ssh <name>@<host> 'tar -kxzf - -C <target-dir>' 

1
Realiza una conexión remota. Primero, es la fuente, lo canaliza a la conexión ssh y lo desempaqueta en el sistema remoto.
huembi

-1

scpsobrescribe los archivos y no hay ningún interruptor que lo detenga, pero puede copiar las cosas, hacer el scp y luego copiar los archivos existentes. Ejemplos:

  1. Copie todos los archivos existentes fuera del camino

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

    scp -r user@server:dir/* ./
    
  3. Copie los archivos originales sobre cualquier cosa que scp haya escrito sobre:

    cp -r original_files/* ./
    

3
Este método no ayuda cuando intentas detener archivos desde un control remoto y retomarlos donde los dejaste. Es decir, si todo el propósito es ahorrar tiempo.
Oliver Williams

-1

Otra forma de lograr esto es hacer un lsen la carpeta de destino:

En la carpeta de destino remota:

ls | awk '{print "mv " $1 " ../copied_data/"}' > mv_copied_data
scp mv_copied_data user@source.server.com:/path/to/source/folder

En la fuente:

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

En destino:

scp -r user@source.server.com:/path/to/source/folder /path/to/destination/foldeer

Por favor no hagas esto. 1. No analices ls . 2. La respuesta es peligrosa si cualquier nombre de archivo contiene - >espacio de nueva línea u otros caracteres especiales. 3. Codifique un bucle for en un script de Python. Generar un programa en tiempo de ejecución es difícil y complicado (incluso cuando lo hacen programadores profesionales), por muchas razones. Generar un script de shell es aún peor: una idea horrible.
ignis
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.