perl压缩没有工作目录文件路径的文件夹

时间:2018-11-26 10:05:49

标签: regex perl zip compression

我正在尝试将包含文件和子文件夹(带有文件)的文件夹压缩到单个zip文件中。我仅限于核心perl模块,因此我尝试使用IO :: Compress :: Zip。我想删除工作目录文件路径,但似乎在压缩文件夹之前以空白的第一个文件夹结尾,就像后面没有尾号的“ /”一样。

use Cwd;
use warnings;
use strict;
use File::Find;
use IO::Compress::Zip qw(:all);

my $cwd = getcwd();
   $cwd =~ s/[\\]/\//g;

print $cwd, "\n";
my $zipdir  = $cwd . "\\source_folder";
my $zip = "source_folder.zip";

my @files = ();

sub process_file {
    next if (($_ eq '.') || ($_ eq '..'));
    if (-d && $_ eq 'fp'){
        $File::Find::prune = 1;
        return;
    }
    push @files, $File::Find::name if -f;
}
find(\&process_file, $cwd . "\\source_folder");

zip \@files  => "$zip", FilterName => sub{ s|\Q$cwd|| }  or die "zip failed: $ZipError\n";

我还尝试使用选项“ CanonicalName => 1”,该选项似乎保留了文件路径,但驱动器号(C :)除外。 用

替换
s[^$dir/][]

什么也没做

s<.*[/\\]><>

离开我时根本没有文件夹结构。

我想念什么?

更新 Resultant Zip contents (blurred to protect the innocent) in 7Zip

红色级别是意外的,不是必需的,Win资源管理器无法看到此级别之外的内容。

2 个答案:

答案 0 :(得分:1)

您的脚本有两个问题。

首先,您要在脚本中混合Windows和Linux / Unix路径。让我说明一下

我已经创建了一个名为 source_folder 的子目录来匹配您的脚本

 $ dir source_folder
 Volume in drive C has no label.
 Volume Serial Number is 7CF0-B66E

 Directory of C:\Scratch\source_folder

26/11/2018  19:48    <DIR>          .
26/11/2018  19:48    <DIR>          ..
26/11/2018  17:27               840 try.pl
01/06/2018  13:02             6,653 url
               2 File(s)          7,493 bytes

在未修改的情况下运行您的脚本时,在Windows资源管理器中查看它时,会得到一个显然空的zip文件。但是,如果我使用命令行解压缩,我会看到source_folder.zip不是空的,但是它具有Windows和Linux / Unix的非标准文件名。

$ unzip -l source_folder.zip
Archive:  source_folder.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      840  2018-11-26 17:27   \source_folder/try.pl
     6651  2018-06-01 13:02   \source_folder/url
---------                     -------
     7491                     2 files

在此行脚本中创建Windows和Unix路径的混合匹配

find(\&process_file, $cwd . "\\source_folder");

您正在将 $ cwd 中的Unix样式路径与Windows部分“ \ source_folder”连接起来。

更改该行以使用正斜杠,而不是反斜杠以获得一致的Unix样式的路径。

find(\&process_file, $cwd . "/source_folder");

第二个问题是这一行

zip \@files  => "$zip", 
        FilterName => sub{ s|\Q$cwd|| },
        BinmodeIn =>1
   or die "zip failed: $ZipError\n";

替代项s|\Q$cwd||需要一个额外的“ /”,例如s|\Q$cwd/||,以确保添加到zip归档文件中的路径是相对路径。所以这行变成

zip \@files  => "$zip", FilterName => sub{ s|\Q$cwd/|| }  or die "zip failed: $ZipError\n";

完成这两项更改后,我可以在命令行中查看zip文件,并在使用命令行解压缩时获得Unix风格的相对路径

$ unzip -l source_folder.zip
Archive:  source_folder.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      840  2018-11-26 17:27   source_folder/try.pl
     6651  2018-06-01 13:02   source_folder/url
---------                     -------
     7491                     2 files

答案 1 :(得分:0)

这对我有用:

use Cwd;
use warnings;
use strict;
use File::Find;
use IO::Compress::Zip qw(:all);
use Data::Dumper;

my $cwd = getcwd();
$cwd =~ s/[\\]/\//g;

print $cwd, "\n";
my $zipdir  = $cwd . "/source_folder";
my $zip = "source_folder.zip";

my @files = ();

sub process_file {
    next if (($_ eq '.') || ($_ eq '..'));
    if (-d && $_ eq 'fp') {
        $File::Find::prune = 1;
        return;
    }
    push @files, $File::Find::name if -f;
}
find(\&process_file, $cwd . "/source_folder");
print Dumper \@files;
zip \@files  => "$zip", FilterName => sub{ s|\Q$cwd/|| }  or die "zip failed: $ZipError\n";

我在对find()的调用中将路径分隔符更改为'/',并在FilterName子句中将其剥离。 控制台:

C:\Users\chris\Desktop\devel\experimente>mkdir source_folder
C:\Users\chris\Desktop\devel\experimente>echo 1 > source_folder/test1.txt
C:\Users\chris\Desktop\devel\experimente>echo 1 > source_folder/test2.txt
C:\Users\chris\Desktop\devel\experimente>perl perlzip.pl
C:/Users/chris/Desktop/devel/experimente
Exiting subroutine via next at perlzip.pl line 19.
$VAR1 = [
      'C:/Users/chris/Desktop/devel/experimente/source_folder/test1.txt',
      'C:/Users/chris/Desktop/devel/experimente/source_folder/test2.txt'
    ];

C:\Users\chris\Desktop\devel\experimente>tar -tf source_folder.zip
source_folder/test1.txt
source_folder/test2.txt