Einen Ordner kopieren und dabei NUR kleinere Dateien im Ziel überschreiben

Einen Ordner kopieren und dabei NUR kleinere Dateien im Ziel überschreiben

Ich habe jede Menge PDFs in mehreren Unterordnern in/home/Benutzer/originaldie ich komprimiert habe mitGhostscript pdfschreibenIn/home/Benutzer/komprimiert.

Ghostscripthat gute Arbeit geleistet und etwa 90 % der Dateien komprimiert, der Rest war jedoch größer als die Originale.

Ich möchtecp /home/Benutzer/komprimiertZu/home/Benutzer/originalÜberschreiben von Dateien, dienurkleiner als die im Ziel, während die größeren übersprungen werden.

Irgendwelche Ideen?

Antwort1

Der folgende findBefehl sollte hierfür funktionieren:

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

Der Schlüsselteil dieser Lösung wird --max-sizebereitgestellt von rsync. Aus dem rsyncHandbuch:

--max-size=SIZE

Dadurch wird rsync angewiesen, die Übertragung von Dateien zu vermeiden, die größer als die angegebene GRÖSSE sind.

Der findBefehl arbeitet also im Zielverzeichnis (/home/user/original) und gibt eine Liste von Dateien zurück. Für jede Datei wird eine bashShell gestartet, die den rsyncBefehl ausführt. Der SIZEParameter für --max-sizedie Option wird festgelegt, indem ein statBefehl für die Zieldatei ausgeführt wird.

Tatsächlich rsyncsieht die Verarbeitungslogik folgendermaßen aus:

  1. Wenn die Quelldatei größer als die Zieldatei ist, --max-sizeverhindert der Parameter die Übertragung der Quelldatei.
  2. Wenn die Quelldatei kleiner als die Zieldatei ist, wird die Übertragung wie erwartet fortgesetzt.

Diese Logik führt dazu, dass nur die kleineren Dateien vom Quellverzeichnis in das Zielverzeichnis übertragen werden.

Ich habe dies auf verschiedene Arten getestet und es funktioniert bei mir wie erwartet. Sie sollten jedoch möglicherweise eine Sicherungskopie des Zielverzeichnisses erstellen, bevor Sie es auf Ihrem System ausprobieren.

Antwort2

Perls-SBetreiber zur Rettung!

Erstellen Sie ein ausführbares Perl-Skript 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;

Und führen Sie es für jede Datei im Originalverzeichnis aus:

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

Oder schreiben Sie in Perl auch den Teilbaum, der dorthin führt:

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

verwandte Informationen