Как заархивировать набор файлов с помощью Perl в Win32, сохранив пути к файлам?

ОБНАРУЖЕНА ПРОБЛЕМА. Я оставляю вопрос здесь, на случай, если другие столкнутся с той же проблемой, с которой столкнулся я.

Похоже, я обнаружил ошибку или странную функцию в WinZip 11. Когда я дважды щелкаю файл test2.zip, чтобы увидеть его содержимое, WinZip сообщает мне, что путь к файлу данных - «allcapsname» в нижнем регистре, но когда WinZip извлекает архив (из меню "Извлечь сюда", щелкнув правой кнопкой мыши), он фактически правильно создает каталог "ALLCAPSNAME". Я жаловался на проблему, которая, как мне казалось, у меня была с Archive :: Zip, и все время это была проблема WinZip. Спасибо всем, кто помог разобраться, в чем дело.

Оказывается, чтобы получить путь, который будет отображаться в файле WinZip при использовании Archive :: Tar, вам понадобится эта строка в вашем коде, чтобы заставить Archive :: Tar отклоняться от строгого соответствия POSIX: $ Archive :: Tar :: DO_NOT_USE_PREFIX = 1 ;

ОРИГИНАЛЬНЫЙ ВОПРОС: На данный момент я нашел несколько различных модулей Perl, которые, похоже, способны создавать файлы архивов ZIP, GZIP, TAR или TGZ из моих сценариев Perl. , но я не добился полного успеха ни от одного из них. Почему это так сложно? Это потому, что я на машине с Windows? (Я потратил около 4 часов на эту, казалось бы, простую задачу, и я действительно расстраиваюсь.)

Когда я попробовал Archive :: Tar, мне удалось создать архивный файл, но я не могу получить пути к любому из моих файлов, включенных в архив по той или иной причине. Я пробовал кучу разных вещей в своем коде, и мой tarball всегда показывал файлы с пустыми путями. (Я просматриваю свои архивы с помощью WinZip.)

Когда я попробовал Archive :: Zip, я добился большего успеха и получил фактический путь к каталогу к моим файлам, включенным в файл архива. Единственная проблема заключалась в том, что мой путь к моим файлам где-то по пути был изменен с верхнего регистра на нижний. Почему изменился регистр моего каталога? Я хочу, чтобы фактическое имя каталога оставалось таким, как было.

Я безуспешно пробовал несколько других модулей. Я даже не могу получить образец кода из Archive :: Builder даже для компиляции .

ОРИГИНАЛЬНОЕ ДОБАВЛЕНИЕ К ВОПРОСУ:

Я, наконец, смог создать минимальный исполняемый скрипт, который ясно демонстрирует мои две проблемы, которые я описал выше относительно Archive :: Zip и Archive :: Tar.

use strict;
use warnings;
use Archive::Zip;
use Archive::Tar;

print "Starting...\n";

# Archive::Zip Synopsis (relative path to directory)
my $zip1 = Archive::Zip->new();
$zip1->addFile( 'MyArchiveFiles/file1.txt' )
    or die 'unable to add file to archive';
$zip1->writeToFileNamed('test1.zip');

# Archive::Zip Synopsis (with ALL CAPS DIRECTORY NAME)
my $zip2 = Archive::Zip->new();
$zip2->addFile( 'ALLCAPSNAME/file1.txt' )
    or die 'unable to add file to archive';
$zip2->writeToFileNamed('test2.zip');

# Archive::Tar Synopsis (relative path to directory)
my $tar3 = Archive::Tar->new;
$tar3->add_files( 'MyArchiveFiles/file1.txt' )
    or die 'unable to add file to archive';
$tar3->write('test3.tar');

print "Finished successfully!";

Этот скрипт создает 3 архива. Первый архив содержит файл данных с соответствующим путем "MyArchiveFiles \". Моя проблема возникает, когда имя моего каталога состоит только из заглавных букв. Второй архив содержит файл данных, но путь в архивном файле не "ALLCAPSNAME \", как ожидалось ... это "allcapsname \". Для меня это проблема. Почему он изменил регистр моего пути и как я могу заставить его оставить его в покое?

Третий архив содержит файл данных, но содержит пустой путь к этому файлу. Для меня это проблема. Мне нужен путь в архиве, чтобы при распаковке архива файлы извлекались в соответствующую структуру каталогов.


person Kurt W. Leucht    schedule 20.10.2009    source источник
comment
Даже если мы зададим неявный вопрос: «Чёрт возьми, я делаю что-то не так?» необходимо еще несколько деталей.   -  person Adam Kennedy    schedule 21.10.2009
comment
Вы используете последние версии Archive::Zip и Archive::Tar?   -  person Sinan Ünür    schedule 21.10.2009
comment
Последние версии? Хороший вопрос. Когда я запустил PPM, он сказал, что у меня вообще нет Tar, и сказал, что у меня 1,20 Zip, а последний - 1,30. Я установил оба из PPM, и теперь у меня есть две копии ZIP. В области Perl у меня все еще есть старая версия 1.20, а в области сайта - последняя версия 1.30. Как мне установить в область perl, а не в область сайта, и как узнать, что используется, если у меня есть и то, и другое? Опять расстраивает.   -  person Kurt W. Leucht    schedule 21.10.2009
comment
Я добавил пример кода, который конкретно демонстрирует проблему нижнего регистра в Zip и проблему пустого пути в Tar.   -  person Kurt W. Leucht    schedule 21.10.2009
comment
@Kurt Нет, желательно оставить исходную библиотеку на месте и установить обновления в site области. Обратите внимание, что по умолчанию site/lib появляется перед lib в @INC, что означает, что используется последняя установленная версия библиотеки. По какой-то причине это может вас расстроить, но это не проблема Windows или Perl.   -  person Sinan Ünür    schedule 21.10.2009
comment
Область сайта имеет приоритет над областью perl, AFAIK, поэтому последнее на сайте - это все, что вам нужно.   -  person Kev    schedule 21.10.2009
comment
Я запустил ваш сценарий и опубликовал свои наблюдения в отдельном ответе. Возможно, вы захотите прочитать catb.org/~esr/faqs/smart-questions .html # id382249   -  person Sinan Ünür    schedule 21.10.2009
comment
Я не знал, что имеет приоритет. Вот почему я был разочарован. Теперь я знаю и больше не расстраиваюсь.   -  person Kurt W. Leucht    schedule 22.10.2009


Ответы (5)


У вас есть конкретный вопрос? Следующий код отлично работает в Win32:

#!/usr/bin/perl

use strict;
use warnings;

use Archive::Zip;
use File::Find;

my $zip = Archive::Zip->new;

find(\&wanted, $ENV{TEMP});

$zip->writeToFileNamed('test.zip');

sub wanted {
    return unless /\.txt$/;
    $zip->addFile($File::Find::name);
}

Запустим:

C:\Temp> arc

C:\Temp> unzip -l test.zip

Archive:  test.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
      240  10-16-09 19:19   /Temp/cpan_install_Wb7z.txt
     2401  10-18-09 23:09   /Temp/perldoc_perlfunc_T4adbd85e_aec9c.txt
     2401  10-18-09 23:09   /Temp/perldoc_perlfunc_T4adbd872_bc437.txt
     2718  10-19-09 10:04   /Temp/perldoc_perlfunc_T4adc71e7_f4c64.txt
     2718  10-19-09 10:04   /Temp/perldoc_perlfunc_T4adc71f2_bf08d.txt
     2718  10-19-09 10:04   /Temp/perldoc_perlfunc_T4adc720a_a5c6a.txt
    29188  10-19-09 10:05   /Temp/perldoc_perlfunc_T4adc7226_bd834.txt
     6949  10-20-09 17:31   /Temp/perldoc_perlfunc_T4ade2c1f_d0cf8.txt
     6949  10-20-09 17:32   /Temp/perldoc_perlfunc_T4ade2c50_f2040.txt
   106763  10-19-09 10:00   /Temp/perldoc_perlop_T4adc7103_f4cab.txt
    67948  10-18-09 23:07   /Temp/perldoc_perlvar_T4adbd7d7_d8cda.txt
 --------                   -------
   230993                   11 files

То же для Archive::Tar.

Обновление. Чтобы развеять сомнения в том, что файлы были добавлены в архив с правильным путем, обратите внимание:

C:\Temp> dir *.txt
 Volume in drive C is ****
 Volume Serial Number is ****-****

 Directory of C:\Temp

2009/10/16  07:19 PM               240 cpan_install_wb7z.txt
2009/10/18  11:09 PM             2,401 perldoc_perlfunc_t4adbd85e_aec9c.txt
2009/10/18  11:09 PM             2,401 perldoc_perlfunc_t4adbd872_bc437.txt
...
person Sinan Ünür    schedule 20.10.2009
comment
Я думаю, это показывает то, что на самом деле сказал ОП: эти пути не включены в архив. Они выглядят плоскими, а разделители путей заменены подчеркиванием. - person Kev; 21.10.2009
comment
@Kev: Нет. Файлы perldoc_perlfunc_*_*.txt находятся в моем $ENV{TEMP}. - person Sinan Ünür; 21.10.2009
comment
Кажется, это работает. Смотрю сейчас на свой код, чтобы понять, что я сделал не так. - person Kurt W. Leucht; 21.10.2009
comment
Я просто добавил к исходному коду примера вопроса, который демонстрирует проблему с путями, с которой я столкнулся в Zip, а также демонстрирует проблему с пустым путем, с которой я столкнулся в Tar. - person Kurt W. Leucht; 21.10.2009
comment
Спасибо, что разместили рабочий код. Это было очень похоже на мой код, который не работал должным образом. Только имя моего каталога было заглавными. Похоже, имя моего каталога, написанное заглавными буквами, отображалось в WinZip в нижнем регистре. Думаю, я обнаружил ошибку WinZip или странную функцию. Спасибо, что помогли мне разобраться в проблеме! - person Kurt W. Leucht; 22.10.2009

Как автор Archive :: Builder, это почти наверняка не то, что вы хотеть.

Он предназначен для создания файлов ZIP в памяти с использованием сочетания содержимого диска и созданного кода, а не для архивирования.

person Adam Kennedy    schedule 21.10.2009
comment
Хорошо. Спасибо за публикацию. На самом деле я не понял этого, читая документацию по CPAN. Вы можете прояснить этот момент в следующей редакции. Кроме того, похоже, что в конце одной из строк кода вместо точки с запятой в синопсисе стоит точка. - person Kurt W. Leucht; 21.10.2009

Иногда я слышу ваше разочарование по поводу простых вещей с perl на win32. Если все остальное не помогает, просто запустите версию 7-zip для командной строки, делающую то, что вы хотите, а затем выполните для нее вызов system ().

person Kev    schedule 20.10.2009
comment
Как это на что-нибудь отвечает? - person Sinan Ünür; 21.10.2009
comment
Иногда ответ - плыть. Это неплохое предложение, даже если только на короткий срок, чтобы все заработало, пока вы разбираетесь с остальным. У меня были проблемы с Archive :: Zip за последние пару недель, и я вкратце сделал то, что описал Кев. - person brian d foy; 21.10.2009
comment
О, не поймите меня неправильно, я всецело за то, чтобы запускать программы из командной строки, а не пытаться их написать. Однако я предполагаю, что проблемы OP на самом деле не связаны с Archive::Zip, Archive::Tar или даже с Windows. Итак, у нас в основном есть пост, в котором говорится: Windows - отстой, и еще один, в котором говорится: Я чувствую вашу боль, но мы не знаем, что на самом деле не так, и почему это не так и как это можно исправить. Итак, я рекомендую Курту Лейхту либо разместить свои жалобы в своем блоге, либо разместить здесь некоторые подробности, чтобы этот пост действительно мог помочь другим. - person Sinan Ünür; 21.10.2009
comment
Что ж, я надеялся, что кто-то опубликует рабочие примеры, и на первый взгляд похоже, что пример Синан работает. У меня есть домашняя работа, чтобы выяснить, что мой код делал неправильно. Любые опубликованные рабочие примеры помогут пользователям. Затем, когда я публикую то, что на самом деле делал не так, это также может помочь некоторым пользователям. - person Kurt W. Leucht; 21.10.2009
comment
В этом случае мне не разрешено прыгать, потому что это производственный код. - person Kurt W. Leucht; 21.10.2009
comment
@Sinan: Я думал, что он отвечает, по крайней мере, на заголовок OP. @ Курт: Достаточно честно. :) - person Kev; 21.10.2009

Я собираюсь ответить на вопросы, поднятые в новой информации, которую вы добавили в сообщение. Я запустил твой сценарий. Вот результаты:

C:\Temp\a> unzip -l test1.zip
Archive:  test1.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  10-21-09 13:03   MyArchiveFiles/file1.txt
 --------                   -------
        0                   1 file
C:\Temp\a\d> unzip ../test1.zip
Archive:  ../test1.zip
 extracting: MyArchiveFiles/file1.txt

C:\Temp\a\d> dir /s
...
 Directory of C:\Temp\a\d

2009/10/21  01:09 PM              MyArchiveFiles

 Directory of C:\Temp\a\d\MyArchiveFiles

2009/10/21  01:03 PM                 0 file1.txt
C:\Temp\a\d> unzip ..\test2.zip
Archive:  ..\test2.zip
 extracting: ALLCAPSNAME/file1.txt

C:\Temp\a\d> dir /s

 Directory of C:\Temp\a\d

2009/10/21  01:11 PM              ALLCAPSNAME
2009/10/21  01:09 PM              MyArchiveFiles

 Directory of C:\Temp\a\d\ALLCAPSNAME

2009/10/21  01:07 PM                 0 file1.txt
C:\Temp\a\d> tar -xvf ..\test3.tar
tar: Record size = 3 blocks
MyArchiveFiles/file1.txt

C:\Temp\a\d> dir /s

2009/10/21  01:13 PM              MyArchiveFiles

 Directory of C:\Temp\a\d\MyArchiveFiles

2009/10/21  01:03 PM                 0 file1.txt

Я убрал часть постороннего вывода от dir, но я надеюсь, что это делает очевидным раз и навсегда, что любые проблемы, с которыми вы сталкиваетесь, не связаны с Windows или Perl, или Archive::Tar или Archive::Zip.

Для записи:

C:\Temp> perl -v

This is perl, v5.10.1 built for MSWin32-x86-multi-thread
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2009, Larry Wall

Binary build 1006 [291086] provided by ActiveState http://www.ActiveState.com
Built Aug 24 2009 13:48:26
C:\Temp> perl -MArchive::Tar -e "print $Archive::Tar::VERSION"
1.52
C:\Temp> perl -MArchive::Zip -e "print $Archive::Zip::VERSION"
1.30
C:\Temp> tar --version
tar (GNU tar) 1.21
C:\Temp> unzip -v
UnZip 5.52 of 28 February 2005, by Cygwin. Original by Info-ZIP.
person Sinan Ünür    schedule 21.10.2009
comment
Думаю, я обнаружил ошибку или странную функцию в WinZip 11. Когда я дважды щелкаю файл test2.zip, чтобы увидеть его содержимое, WinZip сообщает мне, что путь к файлу данных - allcapsname в нижнем регистре, но когда WinZip извлекает архив ( из меню «Извлечь сюда», щелкнув правой кнопкой мыши), он фактически правильно создает каталог ALLCAPSNAME. Я жаловался на проблему, которая, как мне казалось, у меня была с Archive :: Zip, и все время это была проблема WinZip. Спасибо всем, кто помог разобраться, в чем дело. - person Kurt W. Leucht; 22.10.2009
comment
Однако даже после распаковки у меня все еще не было каталога в файле test3.tar. Интересно, почему это работает для вас, и мы запускаем один и тот же тестовый код. Я использую ActiveState Perl и имею последний модуль Archive :: Tar. - person Kurt W. Leucht; 22.10.2009
comment
@Kurt Неужели это так сложно? Я не использую WinZip. - person Sinan Ünür; 22.10.2009
comment
У меня была законная проблема, с которой вполне могут столкнуться другие пользователи Интернета. На этом форуме целесообразно разобраться с проблемой и решением, чтобы будущие пользователи могли быстро и легко найти решение. Вот для чего нужен SO. Если у вас нет времени или терпения, чтобы помочь новым пользователям решить их проблемы, просто игнорируйте их вопросы. На этом форуме неуместно грубить новым пользователям. - person Kurt W. Leucht; 22.10.2009
comment
@Kurt Не будет грубо указать, что иногда, просто иногда, проблема не в ОС, языке или библиотеках. На самом деле, вы пришли сюда не с проблемой. Почему это так сложно? Это потому, что я на машине с Windows? Вы пришли сюда с жалобой. Эти два разные. Мне пришлось очень много работать, чтобы получить конкретное описание проблемы и код для ее решения. - person Sinan Ünür; 22.10.2009
comment
Я не согласен. Я пришел сюда с проблемой. Похоже, вам больно, что это оказалась проблема с WinZip. Если бы вы использовали WinZip, вы, вероятно, в конце концов столкнулись бы с той же проблемой. Теперь проблема решена благодаря вашей и другим помощи. И теперь будущие пользователи, столкнувшиеся с той же проблемой, могут найти ее здесь и сразу же найти решение. SO свое дело сделал. - person Kurt W. Leucht; 22.10.2009

Ответом оказалась проблема с WinZip 11. Так что, если вы просматриваете свои файлы Archive :: Zip с помощью WinZip, просто игнорируйте тот факт, что все пути в верхнем регистре заменены на все в нижнем регистре в графическом интерфейсе WinZip, потому что когда если вы его разархивируете, путь будет указан в верхнем регистре, как и предполагалось.

Что касается проблемы Archive :: Tar, заключающейся в том, что в WinZip вообще не отображается какой-либо путь, вам нужно заставить Archive :: Tar отклониться от строгого соответствия POSIX со следующей строкой, и тогда вы увидите пути в WinZip:

$Archive::Tar::DO_NOT_USE_PREFIX = 1;
person Kurt W. Leucht    schedule 22.10.2009