【问题标题】:How do I archive a set of files using Perl on Win32 while retaining file paths?如何在 Win32 上使用 Perl 归档一组文件,同时保留文件路径?
【发布时间】:2010-12-08 12:21:53
【问题描述】:

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

看起来我在 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 脚本中创建 ZIP 或 GZIP 或 TAR 或 TGZ 归档文件的各种 Perl 模块,但实际上我还没有从其中任何一个中获得完全的成功。为什么这么难?是因为我在 Windows 机器上吗? (到目前为止,我在这个看似简单的任务上浪费了大约 4 个小时,真的很沮丧。)

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

当我尝试Archive::Zip 时,我取得了更大的成功,并且我获得了包含在存档文件中的文件的实际目录路径。唯一的问题是我的文件路径从大写变为小写。为什么它改变了我的目录的大小写?我希望实际的目录名称保持原样。

我尝试了其他几个模块,但没有成功。我什至无法从Archive::Builder 获取示例代码来编译。

原始问题附录:

我终于能够创建一个最小的可执行脚本,它清楚地展示了我上面描述的关于 Archive::Zip 和 Archive::Tar 的 2 个问题。

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\”。这对我来说是个问题。为什么它改变了我路径的大小写,我怎么能强迫它不管它?

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

【问题讨论】:

  • 即使我们提出隐含的问题“我做错了吗?”还需要更多细节。
  • 您使用的是最新版本的Archive::ZipArchive::Tar吗?
  • 最新版本?好问题。当我启动 PPM 时,它说我根本没有 Tar,它说我有 1.20 的 Zip,而最新的是 1.30。我从 PPM 安装了两个,现在我有两个 ZIP 副本。在 perl 区域我仍然有旧的 1.20,而在站点区域我有最新的 1.30。我如何安装到 perl 区域而不是站点区域,如果我同时拥有两者,我如何知道使用哪个?再次令人沮丧。
  • @Kurt 不,最好保留原始库并在site 区域安装升级。请注意,默认情况下,site/lib@INC 中出现在lib 之前,这意味着使用的是最新安装的库版本。出于某种原因,这可能会让您感到沮丧,但这不是 Windows 或 Perl 的问题。
  • 站点区域优先于 perl 区域,AFAIK,因此您只需要最新的站点。

标签: perl winapi path archive tar


【解决方案1】:

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

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

$Archive::Tar::DO_NOT_USE_PREFIX = 1;

【讨论】:

    【解决方案2】:

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

    C:\Temp\a> 解压 -l test1.zip 存档:test1.zip 长度 日期 时间 名称 -------- ---- ---- ---- 0 10-21-09 13:03 MyArchiveFiles/file1.txt -------- -------- 0 1 个文件 C:\Temp\a\d> 解压 ../test1.zip 存档:../test1.zip 提取:MyArchiveFiles/file1.txt C:\Temp\a\d> 目录 /s ... C:\Temp\a\d 目录 2009/10/21 01:09 PM 我的存档文件 C:\Temp\a\d\MyArchiveFiles 目录 2009/10/21 01:03 PM 0 file1.txt C:\Temp\a\d> 解压 ..\test2.zip 存档:..\test2.zip 提取:ALLCAPSNAME/file1.txt C:\Temp\a\d> 目录 /s C:\Temp\a\d 目录 2009/10/21 01:11 PM 2009/10/21 01:09 PM 我的存档文件 C:\Temp\a\d\ALLCAPSNAME 目录 2009/10/21 01:07 PM 0 file1.txt C:\Temp\a\d> 焦油 -xvf ..\test3.tar tar:记录大小 = 3 个块 MyArchiveFiles/file1.txt C:\Temp\a\d> 目录 /s 2009/10/21 01:13 PM 我的存档文件 C:\Temp\a\d\MyArchiveFiles 目录 2009/10/21 01:03 PM 0 file1.txt

    我从dir 中删除了一些无关的输出,但我希望这可以一劳永逸地表明,无论您遇到什么问题都不是由于Windows 或Perl 或Archive::TarArchive::Zip 造成的。

    记录在案:

    C:\Temp> perl -v 这是为 MSWin32-x86-multi-thread 构建的 perl v5.10.1 (带有 2 个已注册的补丁,请参阅 perl -V 了解更多详细信息) 版权所有 1987-2009,拉里·沃尔 二进制构建 1006 [291086] 由 ActiveState http://www.ActiveState.com 提供 建于 2009 年 8 月 24 日 13:48:26 C:\Temp> perl -MArchive::Tar -e "打印 $Archive::Tar::VERSION" 1.52 C:\Temp> perl -MArchive::Zip -e "打印 $Archive::Zip::VERSION" 1.30 C:\Temp> 焦油--版本 焦油 (GNU 焦油) 1.21 C:\Temp> 解压 -v 解压缩 5.52,2005 年 2 月 28 日,由 Cygwin 提供。由 Info-ZIP 原创。

    【讨论】:

    • 我猜我在 WinZip 11 中遇到了错误或奇怪的功能。当我双击 test2.zip 文件查看其内容时,WinZip 告诉我数据文件的路径是“allcapsname”小写,但是当 WinZip 解压存档时(从右键单击解压到此处菜单),它实际上会正确创建“ALLCAPSNAME”目录。我一直在抱怨我认为 Archive::Zip 遇到的问题,而这一直是 WinZip 的问题。感谢所有帮助找出问题所在的人。
    • 即使解压后,我在 test3.tar 文件中仍然没有目录。想知道为什么它对您有用,而且我们正在运行相同的测试代码。我正在使用 ActiveState Perl 并拥有最新的 Archive::Tar 模块。
    • @Kurt 这真的那么难吗?我使用 WinZip。
    • 我遇到了 Internet 上的其他用户可能会遇到的合法问题。在这个论坛上找出问题和解决方案是合适的,以便将来的用户可以快速轻松地找到解决方案。这就是 SO 的用途。如果您没有时间或耐心帮助新用户解决他们的问题,那么请忽略他们的问题。在这个论坛上对新用户无礼是不合适的。
    • @Kurt 指出有时,只是有时,问题不在于操作系统、语言或库并不无礼。事实上,你来这里并没有问题。 “为什么这么难?是因为我在 Windows 机器上吗?”你来这里是为了投诉。两者是不同的。我必须非常努力地获得特定的问题描述和代码。
    【解决方案3】:

    作为Archive::Builder的作者,这几乎肯定不是你想要的。

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

    【讨论】:

    • 好的。感谢您发布。通过阅读 CPAN 文档,我实际上并没有理解这一点。您可能会考虑在下一次修订中更清楚地说明这一点。此外,您的代码行的末尾似乎有一个句点,而不是概要中的分号。
    【解决方案4】:

    您有具体的问题吗?以下代码在 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> 弧 C:\Temp> 解压 -l test.zip 存档:test.zip 长度 日期 时间 名称 -------- ---- ---- ---- 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个文件

    Archive::Tar 同上。

    更新:要消除对文件已使用正确路径添加到存档的任何疑问,请注意:

    C:\Temp> 目录 *.txt 驱动器 C 中的卷为 **** 卷序列号为 ****-**** C:\Temp 目录 2009/10/16 07:19 PM 240 cpan_install_wb7z.txt 2009/10/18 晚上 11:09 2,401 perldoc_perlfunc_t4adbd85e_aec9c.txt 2009/10/18 晚上 11:09 2,401 perldoc_perlfunc_t4adbd872_bc437.txt ...

    【讨论】:

    • 我认为这实际上显示了 OP 所说的:路径不包含在存档中。它们看起来很扁平,路径分隔符更改为下划线。
    • @Kev:不。perldoc_perlfunc_*_*.txt 文件在我的$ENV{TEMP} 中。
    • 这似乎行得通。现在查看我的代码,看看我做错了什么。
    • 我刚刚在原问题示例代码中添加了演示我在Zip中遇到的路径案例问题,它还演示了我在Tar中遇到的空路径问题。
    • 感谢您发布工作代码。它非常接近我没有按预期工作的代码。只有我的目录名全部大写。看起来我的全部大写目录名称在 WinZip 中显示为全部小写。猜猜我发现了一个 WinZip 错误或奇怪的功能。感谢您帮我解决问题!
    【解决方案5】:

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

    【讨论】:

    • 这是怎么回答的?
    • 有时答案是下注。这不是一个坏建议,即使只是在短期内让事情正常进行,而您会弄清楚其余部分。在过去的几周里,我在 Archive::Zip 上遇到了自己的困难,并且按照 Kev 的描述做了短暂的尝试。
    • 哦,别误会我的意思,我完全支持调用命令行程序而不是尝试编写它们。然而,我的猜测是,OP 的问题与Archive::ZipArchive::Tar 甚至Windows 都没有真正的关系。所以,我们基本上有一篇文章说 Windows 糟透了,另一篇说 我感到你的痛苦,但不知道什么是真正的问题,为什么它是错误的,以及如何它可以修复。所以,我的建议是 Kurt W. Leucht 要么在他的博客上发布他的投诉,要么在这里发布一些细节,这样这篇文章就有机会真正帮助他人。
    • 嗯,工作示例是我希望有人发布的,乍一看,Sinan 的示例似乎有效。我现在有一些作业要做,以找出我的代码做错了什么。发布的任何工作示例都将对用户有所帮助。然后,当我发布我实际上做错的事情时,这也可能对一些用户有所帮助。
    • @Sinan:我认为它至少回答了 OP 的标题。 @Kurt:很公平。 :)
    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多