слияние — добавление содержимого двоичного файла в определенном порядке

#linux #perl

#linux #perl

Вопрос:

в исходном каталоге у меня есть несколько двоичных файлов с именами 1.bin, 2.bin, 3.bin и т.д. В каталоге dest у меня есть двоичные файлы с одинаковыми именами, но с другим содержимым. Мне нужно добавить содержимое каталога dest к файлам с тем же именем в исходном каталоге, но также быть уверенным, что содержимое целевого каталога будет добавлено под содержимым исходного каталога. Вот к чему я пришел:

 #!/usr/bin/perl
$source_dir = "/data/source_dir";
$dest_dir   = "/data/dest_dir";
opendir ($source, $source_dir);
@source_files = readdir $source;
foreach $each_file (@source_files){
    if($each !~ /^(.|..)$/) {
        open $file_h , "< $source_dir/$each_file";
        @contents = <$file_h>;
        open $dest_file, ">>$dest_dir/$each_file";
        print $dest_file @contents;
        @contents =();
     }
}
  

Как я могу быть уверен, что 1.bin из каталога dest добавлен — объединен с содержимым исходного каталога?

Как тогда должен выглядеть код?

Комментарии:

1. Первый порядок дня: добавьте use strict; и use warnings; , исправьте ошибки, затем обновите свой вопрос новым кодом.

Ответ №1:

Одно из возможных решений

  • use autodie для автоматической обработки ошибок открытия / закрытия
  • File::Spec для обработки имени пути
  • прочитайте исходный файл как двоичный с помощью File::Slurper
  • откройте файл назначения для добавления в виде двоичного файла
    • используя современную версию с 3 аргументами open()
    • распечатать содержимое в дескриптор целевого файла
 #!/usr/bin/perl
use warnings;
use strict;
use autodie;

use File::Spec;
use File::Slurper qw(read_binary);

my $source_dir = "tmp/source_dir";
my $dest_dir   = "tmp/dest_dir";

opendir(my $source, $source_dir);

foreach my $file (readdir $source) {
    unless ($file =~ /^..?$/) {
        my $content = read_binary(File::Spec->catfile($source_dir, $file));
        open(my $ofh, '>> :raw :bytes', File::Spec->catfile($dest_dir, $file));
        print $ofh $content;
        close($ofh);
    }
}

closedir($source);

exit 0;
  

Тестовый запуск:

 $ ls -lhtR tmp/
...
tmp/dest_dir:
-rw-rw-r--. 1 stefanb stefanb 33 22. 3. 20:32 1.bin
-rw-rw-r--. 1 stefanb stefanb 27 22. 3. 20:32 2.bin
-rw-rw-r--. 1 stefanb stefanb 15 22. 3. 20:32 3.bin

tmp/source_dir:
-rw-rw-r--. 1 stefanb stefanb 11 22. 3. 20:32 1.bin
-rw-rw-r--. 1 stefanb stefanb  9 22. 3. 20:32 2.bin
-rw-rw-r--. 1 stefanb stefanb  5 22. 3. 20:31 3.bin

$ perl dummy.pl

$ ls -lhtR tmp/
...
tmp/dest_dir:
-rw-rw-r--. 1 stefanb stefanb 44 22. 3. 20:34 1.bin
-rw-rw-r--. 1 stefanb stefanb 36 22. 3. 20:34 2.bin
-rw-rw-r--. 1 stefanb stefanb 20 22. 3. 20:34 3.bin

tmp/source_dir:
-rw-rw-r--. 1 stefanb stefanb 11 22. 3. 20:32 1.bin
-rw-rw-r--. 1 stefanb stefanb  9 22. 3. 20:32 2.bin
-rw-rw-r--. 1 stefanb stefanb  5 22. 3. 20:31 3.bin
  

ОБНОВЛЕНИЕ: OP изменил требования, чтобы добавлять только в том случае, если файл назначения существует. unless Блок тогда выглядел бы как:

 my $dest_file = File::Spec->catfile($dest_dir, $file);

# only append if destination file exists
if (-f $dest_file ) {
    my $source_file = File::Spec->catfile($source_dir, $file);
    my $content = read_binary($source_file);
    open(my $ofh, '>> :raw :bytes', $dest_file);
    print "Appending contents of ${source_file} to ${dest_file}n";
    print $ofh $content;
    close($ofh);
}
  

Комментарии:

1. Как можно изменить вышесказанное, чтобы добавить также отчет, чтобы узнать, какие файлы имели совпадение и было добавлено содержимое, а какие нет? Совпадение?