Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl
  1. Perl
  2. ファイル操作
  3. here

複数階層のディレクトリを再帰的にコピー

複数階層のディレクトリを再帰的にコピーするには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::PathFile::Copyevalsysopen関数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 モジュールを使って、ディレクトリの作成とファイルのコピーを繰り返します。トップディレクトリ以外の構成は、コピー元と同じなので、トップディレクトリ名だけを置きかえます。

ディレクトリは、コピーできないので、コピー先の名称で、作成してあげます。

Giblog