複数階層のディレクトリを再帰的にコピー
複数階層のディレクトリを再帰的にコピーするにはFile::Findモジュールを使用します。
use strict;
use warnings;
use File::Path 'mkpath';
use Fcntl;
use File::Find 'find';
use File::Copy 'copy';
use Cwd 'getcwd';
# 準備( ディレクトリとファイルの作成 )
my $top_dir = "dir_20080601_$$";
my @dirs = (
"$top_dir/dir1", "$top_dir/dir1/dir1_1", "$top_dir/dir1/dir1_2",
"$top_dir/dir2",
);
for my $dir (@dirs) {
eval{ mkpath $dir };
if (@!){ die "@!" }
}
my @files = (
"$top_dir/top.txt", "$top_dir/dir1/1.txt",
"$top_dir/dir1/dir1_1/1_1.txt", "$top_dir/dir1/dir1_2/1_2.txt",
"$top_dir/dir2/2.txt"
);
for my $file (@files) {
sysopen( my $fh, $file, O_WRONLY | O_CREAT | O_EXCL )
or die "$file を作成することができません。: $!";
close $fh;
}
print "準備: $top_dir を作成しました。\n\n";
# 再帰的なディレクトリコピーのサンプル
print "1: ディレクトリを再帰的にコピーする。\n";
my $cur_dir = getcwd();
# File::Find は、内部で、chdir を繰り返すので、
# 絶対パスで、コピー先ディレクトリ名を作成。
my $dir_copy_to = "$cur_dir/dir_20080601_${$}_cp";
find(\&recursive_copy, $top_dir);
print "$top_dir が、$dir_copy_to にコピーされました。\n";
# 再帰コピーするための関数
sub recursive_copy {
# コピー元のファイルあるいはディレクトリ
my $file_from = $_;
# コピー元のトップディレクトリを
# コピー先のトップディレクトリに
# 置き換える。
my $file_to = $File::Find::name;
$file_to =~ s#^$top_dir#$dir_copy_to#;
if (-d $file_from) {
# ディレクトリは、コピーできないので、同じ名前で作成。
mkdir $file_to
or die "$file_to を作成することができません。\n";
}
else{
copy $file_from, $file_to
or die "$file_from を $file_to にコピーすることができません。\n";
}
}
(参考)File::Path、File::Copy、eval、sysopen関数、Fcntl
複数階層のディレクトリを再帰的にコピーする
find(\&recursive_copy, $top_dir);
# 再帰コピーするための関数
sub recursive_copy {
# コピー元のファイルあるいはディレクトリ
my $file_from = $_;
# コピー元のトップディレクトリを
# コピー先のトップディレクトリに
# 置き換える。
my $file_to = $File::Find::name;
$file_to =~ s#^$top_dir#$dir_copy_to#;
if (-d $file_from) {
# ディレクトリは、コピーできないので、同じ名前で作成。
mkdir $file_to
or die "$file_to を作成することができません。\n";
}
else {
copy $file_from, $file_to
or die "$file_from を $file_to にコピーすることができません。\n";
}
}
ディレクトリを再帰的にコピーするには、File::Find モジュールを使って、ディレクトリの作成とファイルのコピーを繰り返します。トップディレクトリ以外の構成は、コピー元と同じなので、トップディレクトリ名だけを置きかえます。
ディレクトリは、コピーできないので、コピー先の名称で、作成してあげます。
Perlゼミ

