Copie uma pasta substituindo SOMENTE arquivos menores no destino

Copie uma pasta substituindo SOMENTE arquivos menores no destino

Tenho toneladas de PDFs em várias subpastas em/home/usuário/originalque eu compactei usandoscript fantasma pdfwriteem/home/usuário/comprimido.

script fantasmafez um ótimo trabalho ao compactar cerca de 90% dos arquivos, porém o restante deles acabou maior que os originais.

Eu gostaria deCP /home/usuário/comprimidopara/home/usuário/originalsobrescrevendo arquivos que sãoapenasmenores que os do destino, enquanto os maiores são ignorados.

Alguma ideia?

Responder1

O seguinte findcomando deve funcionar para isso:

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"' _ {} \;

A parte principal desta solução é --max-sizefornecida pelo rsync. Do rsyncmanual:

--max-size=SIZE

Isso diz ao rsync para evitar a transferência de qualquer arquivo maior que o SIZE especificado.

Portanto, o findcomando opera no diretório de destino (/home/user/original) e retorna uma lista de arquivos. Para cada arquivo, ele gera um bashshell que executa o rsynccomando. O SIZEparâmetro para --max-sizeopção é definido executando um statcomando no arquivo de destino.

Com efeito, a rsynclógica de processamento torna-se esta:

  1. Se o arquivo de origem for maior que o arquivo de destino, o --max-sizeparâmetro impedirá que o arquivo de origem seja transferido.
  2. Se o arquivo de origem for menor que o arquivo de destino, a transferência prosseguirá conforme o esperado.

Essa lógica resultará na transferência apenas dos arquivos menores do diretório de origem para o diretório de destino.

Eu testei isso de algumas maneiras diferentes e funciona para mim conforme esperado. No entanto, você pode querer criar um backup do diretório de destino antes de testá-lo em seu sistema.

Responder2

Perl-soperador para o resgate!

Crie um script Perl executável 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;

E execute-o para cada arquivo no diretório original:

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

Ou, uma vez em Perl, escreva a subárvore que caminha até lá também:

#!/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');

informação relacionada