Perlで圧縮ファイルを再帰的に展開する方法
Perlで圧縮ファイルを再帰的に展開する方法を紹介します。
1.はじめに
仕事で、次のように入れ子になっているtar.gzファイルをすべて展開する必要が生じました。
test1.tar.gz
├ test2.tar.gz
│ └ test4.tar.gz
└ test3.tar.gz
└ test5.tar.gz
ということで、Perlを使って圧縮ファイルを再帰的に展開する方法を考えてみました。
よりエレガントな解があるかもしれませんがとりあえず。
2.再帰的に展開するサンプル
次のようなコードを作ってみました。
#!/usr/bin/perl
use strict;
use File::Find;
my $dir = shift;
my @list;
find( \&unzip, $dir );
sub unzip {
if (/(.*\.tgz|.*\.tar\.gz)/) {
my $name = $1;
my $file = "$File::Find::dir/$1";
my @grep = grep /$file/, @list if @list;
if ( !@grep ) {
push @list, $file;
my $result = `tar -zxvf $file`;
find( \&unzip, $dir );
}
}
}
3.解説
File::Findは、再帰的にすべてのファイルを処理するためのモジュールです。
use File::Find;
…中略…
find( \&unzip, $dir );
find()の第1パラメータは関数のリファレンス、第2パラメータは処理したいトップディレクトリです。
呼び出された関数ではカレントディレクトリやファイル名を取得できます。
関数内の「$File::Find::dir」には実行中のカレントディレクトリが格納されています。
つまり、
if (/(.*\.tgz|.*\.tar\.gz)/) {
my $name = $1;
my $file = "$File::Find::dir/$1";
とすることでトップディレクトリからのパスと、拡張子が「tgz」または「tar.gz」のファイル名を取得できます。
次に、後述する再帰呼び出しで同一ファイルに対する展開を避けるために、
my @grep = grep /$file/, @list if @list;
if ( !@grep ) {
push @list, $file;
で配列に展開済のパス・ファイル名を保持しています。
最後にバッククォートを使ってtarコマンドでtar.gzファイルを展開し、展開したアーカイブのためにfindを再帰呼び出しします。
my $result = `tar -zxvf $file`;
find( \&unzip, $dir );
再帰呼び出しをしないと初回起動時に存在するディレクトリしか走査されませんので、ご注意ください。
チェックする拡張子を増やせばzipやgzファイルも同時に展開することが可能です。
Posted by yujiro このページの先頭に戻る
- Perlでansibleライブラリを作成する方法
- perlのCPANモジュールからRPMを作成する方法
- Perlで「Subroutine permission redefined at~」を抑止する方法
- XML::Simpleのインストールでエラーになる場合の対処
- YAML::Tinyで「YAML::Tiny found bad indenting in line~」というエラーになる場合の対処
- Perlの正規表現を使って文字列をまとめて取得する方法
- Perlのハッシュでキーの有無を調べる方法
- perlで配列の途中の要素を削除する方法
- YAML::Tinyでコロンを利用する方法
- Perlで改行コードがCRのファイルを読み込む方法
- Perlで「Possible precedence issue with control flow operator」という警告の対処
- PerlのLWPで「Can't verify SSL peers without knowing which Certificate Authorities to trust」というエラーになったときの対処
- Perl+Windowsでファイルを再帰的にリネームする方法
- Perlプログラムの中でファイルの一部を書き換える方法
- Perlの「Bareword "%s" not allowed while "strict subs" in use~」というエラーについて
トラックバックURL
コメントする
greeting