在目录中递归解压缩文件夹(保留文件夹名称)

时间:2016-09-27 16:25:11

标签: perl

我正在寻找一种方法来解压缩指定目录中的多个文件夹(* .zip)并保留每个文件夹的名称。我希望这是Perl脚本的一部分。我需要使用shell吗?请提出一种方法来实现这一目标。

我尝试过从主Perl脚本调用的以下shell脚本: 但它只解压缩了第一个文件夹,但没有保留文件夹名称。

elif [[ "$process" == "unzip" ]];then
        cd $datapath
        folders="$(ls)"
        cd $home
    for ff in $folders; do
        sname=$ff
                echo $sname
        if [  ! -f $sname ];then
                        cd $datapath
                        cd $sname
                        cmd2="unzip -n '*.zip'"
                        echo $cmd2
                        cmd2=`unzip -n '*.zip'`
                        echo $cmd2
                        cmd3="gunzip -f *.gz"
                        echo $cmd3
                        cmd3=`gunzip -f *.gz`
                        echo $cmd3
                        cd $home
        fi
    done

在Perl脚本中我打电话:

my $cmd2 = `perl MDL_unzip_annotate.sh /data/test_all_runs unzip`;  print "$cmd2";

**Before:**
\data\test_all_runs\SN2-63-OFA_Val_5_Chip2\Test1.zip
\data\test_all_runs\SN2-63-OFA_Val_5_Chip2\Test2.zip

**After:**
\data\test_all_runs\SN2-63-OFA_Val_5_Chip2\Test1\text_stuff.txt
\data\test_all_runs\SN2-63-OFA_Val_5_Chip2\Test2\text-stuff2.txt

2 个答案:

答案 0 :(得分:2)

从评论中可以清楚地看到目录/data/test_all_runs/test中有一些* .zip文件,并且您希望将它们提取到子目录中,该目录下面有zipfile的名称。例如:

<强>之前:

/data/test_all_runs/test/a.zip
/data/test_all_runs/test/b.zip

<强>后:

/data/test_all_runs/test/a.zip
/data/test_all_runs/test/a/file1_from_a.txt
/data/test_all_runs/test/a/file2_from_a.txt
/data/test_all_runs/test/a/file3_from_a.txt
/data/test_all_runs/test/b.zip
/data/test_all_runs/test/b/file1_from_b.txt
/data/test_all_runs/test/b/file2_from_b.txt
/data/test_all_runs/test/b/file3_from_b.txt

如果我理解正确,以下代码可以提供帮助:

#!/usr/bin/env perl

use strict;
use warnings;

sub extract_zips_to_their_folders
{
    my $source_dir = shift;

    # iterate over all *.zip files in $source_dir:
    while( my $zipfile = <$source_dir/*.zip> ) {

        # remove '.zip' from $zipfile and store the result as $tgt_dir.
        # If $zipfile is e.g. '/data/test_all_runs/test/a.zip',
        # then $tgt_dir will be '/data/test_all_runs/test/a'.
        (my $tgt_dir = $zipfile) =~ s/\.zip$//;

        # Call 'unzip' with option '-d $tgt_dir', i.e. unzip
        # the archive to the directory with the same name.
        # 'unzip' will create the directory for you.         
        system("unzip $zipfile -d $tgt_dir");
    }
}

extract_zips_to_their_folders( '/data/test_all_runs/test' );

它调用外部命令unzip。如另一个答案所述,还有Perl模块可用于避免此类外部呼叫。

答案 1 :(得分:0)

使用Archive :: Extract之类的东西。来自documentation

use Archive::Extract;

### build an Archive::Extract object ###
my $ae = Archive::Extract->new( archive => 'foo.tgz' );
# but it works with zip as well!

### extract to cwd() ###
my $ok = $ae->extract;

### extract to /tmp ###
my $ok = $ae->extract( to => '/tmp' );

### what if something went wrong?
my $ok = $ae->extract or die $ae->error;