フォルダ(ディレクトリ)操作を行うには、「ディレクトリ操作関数」を利用します。ここでは、ディレクトリをオープンする「opendir」関数、ディレクトリ内のファイル名を読み出す「readdir」関数、ディレクトリをクローズする「closedir」関数を利用しています。
まず、フォルダは「opendir」関数でオープンします。引数はファイルハンドルとディレクトリですが、ディレクトリの「\」記号は「/」に変更します。したがって「c:\Perl64\html\」というフォルダは、「c:/Perl64/html/」と指定します。また、通常の入力ファイルであれば、「<IN1>」のように指定する部分は、「reddir(IN1)」と指定します。
「readdir」関数は、フォルダ内のファイルの他に、サブディレクトリや自分自身である「.」や親ディレクトリである「..」を出力します。このうち、ディレクトリ以外の通常のファイルだけを判定するためにPerlには「ファイルテスト演算子」があります。
「ファイルテスト演算子」は、「if -f ファイル名の変数」の形式で通常のファイルかどうかが判定できます。「ファイル名の変数」には、ドライブ名も含めたフルパスでファイル名を指定する必要があります。「readdir」関数で呼び出したファイル名と変数「$path」に入れておいたパス名を連結し、フルパスにしてから、「ファイルテスト演算子」を利用しているのは、このためです。ここでも「\」記号は「/」に変更しておきます。
なお、フォルダ名やファイル名にアクセント記号のついた半角アルファベットなどが含まれていると、正常に出力されない場合がありますので、注意してください
実際に応用する場合は、入出力データのファイル名等変更して利用します。
# readdir.pl # 内容 : フォルダ内のファイル名を出力 # Copyright (c) 2002-2013 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>perl readdir.pl # $path = "c:/Perl64/html/"; opendir(IN1,$path); open(OUT1,">filename.txt"); while ($filename = readdir(IN1)) { print OUT1 $filename,"\n" if -f $path.$filename; } closedir(IN1); close(OUT1);
ファイルの出力
print OUT1 $filename,"\n" if -f $path.$filename;
$pathと$filenameを連結することでフルパスのファイル名になります。通常のファイルかどうかの判定はフルパスで行いますので、「if -f $path.$filename;」で判定します。特定の拡張子のファイル名だけにしたい場合は、以下のようにします(以下は拡張子が"html"の場合です)。
if ($filename =~ /\.html/) { print OUT1 $filename,"\n"; }
Active.css activeperl.html Artistic.txt blank.html changes.html Copyright.html displayToc.js EULA-Community_License.rtf EULA-Community_License.txt favicon.ico index.html install.html perlmain.html perltoc.html readme.html release.html resources.html scineplex.css tocHeader.css tocParas.js tocTab.js topframe.html
. .. Active.css activeperl.html Artistic.txt bin blank.html changes.html Components Copyright.html displayToc.js EULA-Community_License.rtf EULA-Community_License.txt faq favicon.ico images index.html install.html lib perlmain.html perltoc.html readme.html release.html resources.html scineplex.css site tocHeader.css tocParas.js tocTab.js topframe.html Windows
上記は特定のフォルダだけを対象にしたものですが、フォルダの中にサブフォルダが存在する場合、サブフォルダの配下にあるファイルも含めたファイル名を出力するスクリプトは以下のようになります。
サブフォルダの配下にあるファイルも含めたファイル名を出力しますので、「再帰処理」を行います。再帰処理でのポイントはローカル変数を適切に使用することです。ローカル変数は「my」宣言で指定できます。
下記の例では、"c:\Perl64\html\"のフォルダにあるファイルをサブフォルダも含めて、出力しています。実際に応用する場合は、入出力データのファイル名等変更して利用します。
# readdir2.pl # 内容 : フォルダ内のファイル名を出力 # (サブフォルダ内もすべて出力) # Copyright (c) 2013 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>perl readdir2.pl # $dir = "c:/Perl64/html/"; open(OUT1,">temp.txt"); file_name($dir); sub file_name() { my ($dir) = @_; opendir(IN1,$dir); my @filename = readdir(IN1); my $i; for ($i = 0; $i <= $#filename; $i++) { # フォルダ以外の場合 if (-f $dir.$filename[$i]) { $out1 = join("\t",$filename[$i],$dir); print OUT1 "$out1\n"; } # フォルダの場合(カレントフォルダと親フォルダを除く) elsif (($filename[$i] ne ".") && ($filename[$i] ne "..")) { my $sv_dir = $dir; $dir = $dir.$filename[$i]."/"; # サブフォルダ内の処理 file_name($dir); # カレントフォルダに戻る $dir = $sv_dir; } } } closedir(IN1); close(OUT1); # open(IN1,"temp.txt"); open(OUT1,">filename.txt"); # ソートキーの入っている項目番号 @sortkey = (1,0); # ソートキーをセットするハッシュのキー $key = undef; # ソート用のキーと1行分レコードをセットするハッシュ %sort_record = (); # 入力ファイルを全部読み込む。 @record = <IN1>; # ソートキーとなる項目番号からソートキーとなる文字列を作っておく。 #recno番目のレコードがrecordである。 foreach $recno (0..$#record) { chomp($record[$recno]); # 入力ファイルをタブで分解する。 @in1 = split("\t",$record[$recno],-1); # ソートキーとなる項目の内容をタブで連結してハッシュのキーとする。 foreach $sortno (@sortkey) { $key .= lc($in1[$sortno]) . "\t"; } # 同じ値を持つキーが複数存在する場合に以下のように指定する。 $key .= sprintf("%08d",$recno); # レコードをハッシュの値としてセットする。 $sort_record{$key} = $record[$recno]; $key = undef; } # ハッシュのキーをソートし、キー順にレコードを出力する。 foreach $recno (sort keys %sort_record) { print OUT1 "$sort_record{$recno}\n"; } close(IN1); close(OUT1);
フォルダの指定
$dir = "c:/Perl64/html/"; file_name($dir);
$dirには出力するフォルダをドライブ名も含めて、指定します。ただし「\」は「/」に変えます。そして、$dirを引数にして、サブプログラムを呼び出します。
サブプログラムの初期値設定
sub file_name() { my ($dir) = @_; opendir(IN1,$dir); my @filename = readdir(IN1);
サブプログラムの内部では、引数「@_」をmy宣言をした変数にセットします。これにより、サブプログラム内部で変更した結果は呼び出したときの引数に影響を与えずに使用できるようになります。左辺の「my ($dir)」はリストである点に注意してください。「my $dir」とすると引数の個数である"1"がセットされてしまいます。また、右辺に「readdir」関数、左辺に配列変数を置くと、「readdir」関数で取得したファイル名がすべて、「@filename」に一度にセットされます。
ファイル名出力
for ($i = 0; $i <= $#filename; $i++) { # フォルダ以外の場合 if (-f $dir.$filename[$i]) { $out1 = join("\t",$filename[$i],$dir); print OUT1 "$out1\n"; } # フォルダの場合(カレントフォルダと親フォルダを除く) elsif (($filename[$i] ne ".") && ($filename[$i] ne "..")) { my $sv_dir = $dir; $dir = $dir.$filename[$i]."/"; # サブフォルダ内の処理 file_name($dir); # カレントフォルダに戻る $dir = $sv_dir; } }
フォルダ内で通常のファイル(サブフォルダ以外)であれば、ファイル名とフォルダ名をあわせて出力します。また、サブフォルダの場合はカレントフォルダと親フォルダを除いて、再帰処理でサブフォルダ内の処理を行います。
再帰処理を行う場合は、カレントフォルダ名をmy宣言をした変数に保存します。これにより、サブフォルダ内の処理を終わった後、元のフォルダの処理が続行できるようになります。ファイル名の並べ替え
open(IN1,"temp.txt"); open(OUT1,">filename.txt"); # ソートキーの入っている項目番号 @sortkey = (1,0); # ソートキーをセットするハッシュのキー $key = undef; # ソート用のキーと1行分レコードをセットするハッシュ %sort_record = (); # 入力ファイルを全部読み込む。 @record = <IN1>; # ソートキーとなる項目番号からソートキーとなる文字列を作っておく。 #recno番目のレコードがrecordである。 foreach $recno (0..$#record) { chomp($record[$recno]); # 入力ファイルをタブで分解する。 @in1 = split("\t",$record[$recno],-1); # ソートキーとなる項目の内容をタブで連結してハッシュのキーとする。 foreach $sortno (@sortkey) { $key .= lc($in1[$sortno]) . "\t"; } # 同じ値を持つキーが複数存在する場合に以下のように指定する。 $key .= sprintf("%08d",$recno); # レコードをハッシュの値としてセットする。 $sort_record{$key} = $record[$recno]; $key = undef; } # ハッシュのキーをソートし、キー順にレコードを出力する。 foreach $recno (sort keys %sort_record) { print OUT1 "$sort_record{$recno}\n"; } close(IN1); close(OUT1);
出力したファイルをフォルダ名順のファイル名順で並べ替えています。ドライブ名とフォルダ名つきのファイル名を出力したい場合は、出力する箇所を以下のように変更します。
# ハッシュのキーをソートし、キー順にレコードを出力する。 foreach $recno (sort keys %sort_record) { @temp = split("\t",$sort_record{$recno}); $out1 = $temp[1].$temp[0]; print OUT1 "$out1\n"; }
Active.css c:/Perl64/html/ activeperl.html c:/Perl64/html/ Artistic.txt c:/Perl64/html/ blank.html c:/Perl64/html/ changes.html c:/Perl64/html/ Copyright.html c:/Perl64/html/ displayToc.js c:/Perl64/html/ EULA-Community_License.rtf c:/Perl64/html/ EULA-Community_License.txt c:/Perl64/html/ favicon.ico c:/Perl64/html/ index.html c:/Perl64/html/ install.html c:/Perl64/html/ perlmain.html c:/Perl64/html/ perltoc.html c:/Perl64/html/ readme.html c:/Perl64/html/ release.html c:/Perl64/html/ resources.html c:/Perl64/html/ scineplex.css c:/Perl64/html/ tocHeader.css c:/Perl64/html/ tocParas.js c:/Perl64/html/ tocTab.js c:/Perl64/html/ topframe.html c:/Perl64/html/ ap-iis-config.html c:/Perl64/html/bin/ ap-update-html.html c:/Perl64/html/bin/ ap-user-guide.html c:/Perl64/html/bin/ c2ph.html c:/Perl64/html/bin/ ・・・・・<以下略>
c:/Perl64/html/Active.css c:/Perl64/html/activeperl.html c:/Perl64/html/Artistic.txt c:/Perl64/html/blank.html c:/Perl64/html/changes.html c:/Perl64/html/Copyright.html c:/Perl64/html/displayToc.js c:/Perl64/html/EULA-Community_License.rtf c:/Perl64/html/EULA-Community_License.txt c:/Perl64/html/favicon.ico c:/Perl64/html/index.html c:/Perl64/html/install.html c:/Perl64/html/perlmain.html c:/Perl64/html/perltoc.html c:/Perl64/html/readme.html c:/Perl64/html/release.html c:/Perl64/html/resources.html c:/Perl64/html/scineplex.css c:/Perl64/html/tocHeader.css c:/Perl64/html/tocParas.js c:/Perl64/html/tocTab.js c:/Perl64/html/topframe.html c:/Perl64/html/bin/ap-iis-config.html c:/Perl64/html/bin/ap-update-html.html c:/Perl64/html/bin/ap-user-guide.html c:/Perl64/html/bin/c2ph.html ・・・・・<以下略>