アーカイブ内のファイル名が歪んでおり、?-s*-sや!-sなどの無効なファイルシステム文字が含まれているか、通常のアーカイブツールが混乱する可能性がある非常に長いファイル名とディレクトリ名を含むZIPおよびRARアーカイブが複数あります。生成されたファイルがまったく認識されない可能性があります。コンテンツだけが重要なので、これらのアーカイブのファイルをfile0、file1、file2などの一般的な名前を持つフラット構造の単一ディレクトリに抽出したいと思います。最も簡単な方法は何ですか?
答え1
Daniel S. Sterlingによって書かれたPerlスクリプトhttps://gist.github.com/eqhmcow/5389877(で参照IO::圧縮解除::圧縮解除)必要な作業をほとんど行うようです。
- 46行目を次に変更します。
my $status, $filenumber = 0;
- 注釈行52-54(
#
各行の先頭に配置) - 61行目を次に変更してください。
my $destfile = "file" . $filenumber++;
これらの修正後の完全なスクリプトは、参照用に以下に表示されます。
#!/usr/bin/perl
# example perl code, this may not actually run without tweaking, especially on Windows
use strict;
use warnings;
=pod
IO::Uncompress::Unzip works great to process zip files; but, it doesn't include a routine to actually
extract an entire zip file.
Other modules like Archive::Zip include their own unzip routines, which aren't as robust as IO::Uncompress::Unzip;
eg. they don't work on zip64 archive files.
So, the following is code to actually use IO::Uncompress::Unzip to extract a zip file.
=cut
use File::Spec::Functions qw(splitpath);
use IO::File;
use IO::Uncompress::Unzip qw($UnzipError);
use File::Path qw(mkpath);
# example code to call unzip:
unzip(shift);
=head2 unzip
Extract a zip file, using IO::Uncompress::Unzip.
Arguments: file to extract, destination path
unzip('stuff.zip', '/tmp/unzipped');
=cut
sub unzip {
my ($file, $dest) = @_;
die 'Need a file argument' unless defined $file;
$dest = "." unless defined $dest;
my $u = IO::Uncompress::Unzip->new($file)
or die "Cannot open $file: $UnzipError";
my $status, $filenumber = 0;
for ($status = 1; $status > 0; $status = $u->nextStream()) {
my $header = $u->getHeaderInfo();
my (undef, $path, $name) = splitpath($header->{Name});
my $destdir = "$dest/$path";
# unless (-d $destdir) {
# mkpath($destdir) or die "Couldn't mkdir $destdir: $!";
# }
if ($name =~ m!/$!) {
last if $status < 0;
next;
}
my $destfile = "file" . $filenumber++;
my $buff;
my $fh = IO::File->new($destfile, "w")
or die "Couldn't write to $destfile: $!";
while (($status = $u->read($buff)) > 0) {
$fh->write($buff);
}
$fh->close();
my $stored_time = $header->{'Time'};
utime ($stored_time, $stored_time, $destfile)
or die "Couldn't touch $destfile: $!";
}
die "Error processing $file: $!\n"
if $status < 0 ;
return;
}
1;