web-dev-qa-db-ja.com

宛先の小さいファイルのみを上書きするフォルダをコピーします

/ home/user/originalの複数のサブフォルダーに大量のPDFがあり、ghostscriptを使用して圧縮しましたpdfwritein/ home/user/compressed

ghostscriptは、ファイルの約90%を圧縮するのに優れた仕事をしましたが、残りのファイルは元のファイルよりも大きくなりました。

cp/ home/user/compressedto/ home/user/original宛先のファイルよりものみ小さいファイルを上書きしますが、大きいファイルはスキップしました。

何か案は?

2
Umer

次のfindコマンドはこれに対して機能するはずです。

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

このソリューションの重要な部分は、rsyncによって提供される--max-sizeです。 rsyncマニュアルから:

--max-size=SIZE

これは、指定されたSIZEより大きいファイルを転送しないようにrsyncに指示します。

したがって、findコマンドは宛先ディレクトリ(/ home/user/original)で動作し、ファイルのリストを返します。ファイルごとに、bashコマンドを実行するrsyncシェルを生成します。 --max-sizeオプションのSIZEパラメーターは、宛先ファイルに対してstatコマンドを実行することによって設定されます。

事実上、rsync処理ロジックは次のようになります。

  1. ソースファイルが宛先ファイルよりも大きい場合、--max-sizeパラメータはソースファイルが転送されないようにします。
  2. ソースファイルが宛先ファイルよりも小さい場合、転送は期待どおりに続行されます。

このロジックにより、小さいファイルのみがソースディレクトリから宛先ディレクトリに転送されます。

私はこれをいくつかの異なる方法でテストしましたが、期待どおりに機能します。ただし、システムで試す前に、宛先ディレクトリのバックアップを作成することをお勧めします。

1
Haxiel

Perlの -s 演算子が助けになります!

実行可能なPerlスクリプトを作成する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;

そして、元のディレクトリ内のファイルごとに実行します。

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

または、Perlに入ったら、そこを歩くサブツリーも記述します。

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