我正在尝试将包含文件和子文件夹(带有文件)的文件夹压缩到单个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<.*[/\\]><>
离开我时根本没有文件夹结构。
我想念什么?
红色级别是意外的,不是必需的,Win资源管理器无法看到此级别之外的内容。
答案 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