Copie una carpeta sobrescribiendo SÓLO archivos más pequeños en el destino

Copie una carpeta sobrescribiendo SÓLO archivos más pequeños en el destino

Tengo toneladas de archivos PDF en varias subcarpetas en/inicio/usuario/originalque he comprimido usandoguión fantasma pdfescribiren/home/usuario/comprimido.

guión fantasmaha hecho un gran trabajo al comprimir alrededor del 90% de los archivos, sin embargo, el resto terminó siendo más grande que los originales.

Me gustaríaCP /home/usuario/comprimidoa/inicio/usuario/originalsobrescribir archivos que estánsolomás pequeños que los de destino mientras que los más grandes se omiten.

¿Algunas ideas?

Respuesta1

El siguiente findcomando debería funcionar para esto:

cd /home/user/original
find . -type f -exec bash -c 'file="$1"; rsync --max-size=$(stat -c '%s' "$file") "/home/user/compressed/$file" "/home/user/original/$file"' _ {} \;

La parte clave de esta solución es la --max-sizeproporcionada por rsync. Del rsyncmanual:

--max-size=SIZE

Esto le dice a rsync que evite transferir cualquier archivo que sea más grande que el TAMAÑO especificado.

Entonces el findcomando opera en el directorio de destino (/home/user/original) y devuelve una lista de archivos. Para cada archivo, genera un bashshell que ejecuta el rsynccomando. El SIZEparámetro de --max-sizela opción se establece ejecutando un statcomando en el archivo de destino.

En efecto, la rsynclógica de procesamiento pasa a ser la siguiente:

  1. Si el archivo de origen es más grande que el archivo de destino, el --max-sizeparámetro impedirá que se transfiera el archivo de origen.
  2. Si el archivo de origen es más pequeño que el archivo de destino, la transferencia se realizará según lo esperado.

Esta lógica dará como resultado que solo los archivos más pequeños se transfieran desde el directorio de origen al directorio de destino.

He probado esto de diferentes maneras y funciona como se esperaba. Sin embargo, es posible que desee crear una copia de seguridad del directorio de destino antes de probarlo en su sistema.

Respuesta2

Perl-soperador al rescate!

Cree un script Perl ejecutable overwrite-smaller:

#!/bin/perl
use warnings;
use strict;
use File::Copy;

my $file = shift;
(my $compressed = $file) =~ s/original/compressed/;
copy($compressed, $file) if -s $compressed < -s $file;

Y ejecútelo para cada archivo en el directorio original:

find /home/user/original -type f -exec overwrite-smaller {} \;

O, una vez en Perl, escribe el subárbol que camina allí también:

#!/usr/bin/perl
use warnings;
use strict;

use File::Copy;
use File::Find;

find({no_chdir => 1,
      wanted   => sub {
          my $file = $File::Find::name;
          -f $file or return;
          (my $compressed = $file) =~ s/original/compressed/;
          copy($compressed, $file) if -s $compressed < -s $file;
    }}, 'original');

información relacionada