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

时间:2009-10-20 21:14:23

标签: perl winapi path archive tar

找到了问题。 我在这里留下了这个问题,以防其他人遇到我遇到的同样问题。

看起来我在WinZip 11中遇到了一个bug或一个奇怪的功能。当我双击test2.zip文件查看其内容时,WinZip告诉我数据文件的路径是小写的“allcapsname”,但是当WinZip提取存档时(从右键单击Extract to here菜单),它实际上正确地创建了“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时,我成功创建了存档文件,但由于某种原因,我无法获得tar包中包含的任何文件的路径。我在我的代码中尝试了很多不同的东西,我的tarball总是用空路径显示那里的文件。 (我正在使用WinZip查看我的tarball。)

当我尝试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”。这对我来说是个问题。为什么它改变了我的道路的情况,我怎么能强迫它离开呢?

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

5 个答案:

答案 0 :(得分: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> 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
...

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

我将回答您添加到帖子中的新信息中提出的问题。我跑了你的剧本。结果如下:

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或{ {1}}。

记录:

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.

答案 4 :(得分:0)

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

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

$Archive::Tar::DO_NOT_USE_PREFIX = 1;