如何在 Win32 上使用 Perl 归档一组文件,同时保留文件路径?

发布于 2024-08-08 14:02:00 字数 2361 浏览 8 评论 0原文

发现问题。不过,我将问题留在这里,以防其他人遇到与我相同的问题。

看起来我在 WinZip 11 中遇到了错误或奇怪的功能。当我双击 test2.zip 文件查看其内容时,WinZip 告诉我数据文件的路径是小写的“allcapsname”,但是当 WinZip 解压时存档(从右键单击提取到此处菜单),它实际上正确创建了“ALLCAPSNAME”目录。我一直在抱怨 Archive::Zip 遇到的一个问题,但它一直是 WinZip 问题。感谢所有帮助找出问题所在的人。

事实证明,要在使用 Archive::Tar 时获取在 WinZip 文件中显示的路径,您需要在代码中使用此行来强制 Archive::Tar 偏离严格的 POSIX 合规性: $Archive::Tar::DO_NOT_USE_PREFIX = 1;

原始问题: 到目前为止,我已经发现了一些不同的 Perl 模块,它们似乎能够从我的 Perl 脚本中创建 ZIP 或 GZIP 或 TAR 或 TGZ 存档文件,但实际上我还没有从其中任何一个中获得完全的成功。为什么这么难?是因为我使用的是 Windows 机器吗? (到目前为止,我在这个看似简单的任务上浪费了大约 4 个小时,而且真的很沮丧。)

当我尝试 Archive::Tar 我成功创建了存档文件,但由于某种原因我无法获取 tarball 中包含的任何文件的路径。我在代码中尝试了很多不同的东西,而我的 tarball 总是显示其中的文件带有空路径。 (我正在使用 WinZip 查看我的 tarball。)

当我尝试 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\”。这对我来说是个问题。为什么它改变了我的道路,我怎样才能强迫它不去管它呢?

第三个存档包含数据文件,但包含该文件的空路径。这对我来说是个问题。我需要存档中的路径,以便在解压存档时将文件提取到适当的目录结构中。

PROBLEM FOUND. I'm leaving the question here, though, in case others run into the same problem I ran into.

It looks like I encountered a bug or a weird feature in WinZip 11. When I double click the test2.zip file to see its contents, WinZip tells me the path to the data file is "allcapsname" in lower case, but when WinZip extracts the archive (from a right-click Extract to here menu), it actually creates the "ALLCAPSNAME" directory properly. I was complaining about a problem I thought I was having with Archive::Zip and it was a WinZip problem the whole time. Thanks to all who helped figure out what was wrong.

Turns out that to get the path to show up in WinZip file while using Archive::Tar, you need this line in your code to force Archive::Tar to deviate from strict POSIX compliance:
$Archive::Tar::DO_NOT_USE_PREFIX = 1;

ORIGINAL QUESTION:
I've found a handful of various Perl modules so far that appear to be capable of creating ZIP or GZIP or TAR or TGZ archive files from within my Perl scripts, but I haven't actually had complete success from any of them. Why is this so hard? Is it because I'm on a Windows machine? (I've wasted about 4 hours on this seemingly simple task so far and am really getting frustrated.)

When I tried Archive::Tar I had success creating the archive file, but I was not able to get the paths to any of my files included in the tarball for some reason or another. I tried a bunch of different things in my code and my tarball always showed the files in there with empty paths. (I'm looking at my tarballs using WinZip.)

When I tried Archive::Zip I had more success and I got the actual directory path to my files included in the archive file. The only problem was that my path to my files was somewhere along the way changed from upper case to lower case. Why did it change the case of my directory? I want the actual directory name to remain exactly as it was.

I tried a few other modules without any success. I can't even get the sample code from Archive::Builder to even compile.

ORIGINAL QUESTION ADDENDUM:

I have finally been able to create a minimal executable script that clearly demonstrates my 2 problems that I described above regarding Archive::Zip and 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!";

This script creates 3 archives. The first archive contains the data file with the appropriate path of "MyArchiveFiles\". My problem occurs when my directory name is all caps. The second archive contains the data file, but the path in the archive file is not "ALLCAPSNAME\" as expected ... it is "allcapsname\". This is a problem for me. Why did it change the case of my path and how can I force it to leave it alone?

The third archive contains the data file but it contains an empty path for that file. This is a problem for me. I need the path to be in the archive so that when I unpack the archive the files are extracted into the appropriate directory structure.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜空下最亮的亮点 2024-08-15 14:02:00

您有具体问题吗?以下代码在 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
...

Do you have a specific question? The following code works perfectly fine on 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);
}

Let's run it:

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

Ditto for Archive::Tar.

Update: To clear up any doubt that the files were added to the archive with the correct path, note:

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
...
你对谁都笑 2024-08-15 14:02:00

作为 Archive::Builder 的作者,几乎可以肯定它不是您想要的想。

它旨在使用磁盘和代码生成内容的混合在内存中生成 ZIP 文件,而不是用于存档。

Speaking as the author of Archive::Builder, it is almost certainly not what you want.

It's meant for generating ZIP files in memory using a mix of disk and code-generated content, not for archiving.

甜嗑 2024-08-15 14:02:00

我听到您有时对 win32 上的 Perl 简单的事情感到沮丧。如果一切都失败了,只需获取 7-zip 的命令行版本来执行您想要的操作,然后对其进行 system() 调用。

I hear your frustration of simple things sometimes with perl on win32. If all else fails, just get a command-line version of 7-zip doing what you want, and then do a system() call to it.

拥抱影子 2024-08-15 14:02:00

我将回答您在帖子中添加的新信息中提出的观点。我运行了你的脚本。结果如下:

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::TarArchive::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.

I am going to answer the points raised in the new information you added to the post. I ran your script. Here are the results:

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

I cut away some of the extraneous output from dir, but I hope this makes it obvious once and for all that whatever problems you are experience are not due to Windows or Perl or Archive::Tar or Archive::Zip.

For the record:

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.
网白 2024-08-15 14:02:00

答案是 WinZip 11 的问题。因此,如果您使用 WinZip 查看 Archive::Zip 文件,只需忽略 WinZip GUI 中所有大写路径都更改为小写的事实,因为当当你实际解压它时,路径将按预期全部大写。

至于 Archive::Tar 在 WinZip 中根本看不到任何路径的问题,您需要强制 Archive::Tar 偏离严格的 POSIX 合规性,如下行,然后您将在 WinZip 中看到路径:

$Archive::Tar::DO_NOT_USE_PREFIX = 1;

The answer turned out to be an issue with WinZip 11. So if you're looking at your Archive::Zip files using WinZip, just ignore the fact that the all upper case paths are changed to all lower case in the WinZip GUI because when you actually unzip it, the path will be all upper case as intended.

As far as the Archive::Tar problem of not seeing any path at all in WinZip, you need to force Archive::Tar to deviate from strict POSIX compliance with the following line and then you will see the paths in WinZip:

$Archive::Tar::DO_NOT_USE_PREFIX = 1;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文