ディレクトリを作成するにはmkdir関数を使います。
mkdir $dirname [, $mode ]
dirnameにはディレクトリ名を指定します。$modeは省略可能で、0777のような8進数の数値で作成するディレクトリに与えるパーミッションを指定します。 $modeが省略されると、作成するディレクトリのパーミッションは0777に設定されます。
Perlのファイル操作はC等と同じように、(1) ファイルのオープン、(2) ファイルの読み書き、(3) ファイルのクローズという手順で行われます。
ファイルはopen演算子を使ってオープンしてファイルハンドルを取得します。ファイルハンドルはこれ以降のファイル操作で必要となります。openはファイルのオープンに失敗すると偽の値を返します。
読み込み用オープン | open ( FILE_HANDLE, "< filename"); |
書き込み用にオープン(ファイルを新規に作成) | open ( FILE_HANDLE, "> filename"); |
書き込み用(追加)にオープン | open ( FILE_HANDLE, ">> filename"); |
読み書き用にオープン | open ( FILE_HANDLE, "+> filename"); |
open ( FILE_HANDLE, "+< filename"); | |
コマンドの入力に書き込む(*1) | open ( FILE_HANDLE, "| command"); |
コマンドの出力を読み込む(*2) | open ( FILE_HANDLE, "command |"); |
*1 ファイルオープの際にcommandで指定されたコマンドを起動します。
ファイルをクローズするには、ファイルハンドルをcloseに渡します。
close ( FILE_HANDLE );
Perlでは標準入出力のファイルハンドルはSTDIN, STDOUT, STDERRとなります。実はCと同じように小文字のファイルハンドルstdin, stdout,stderrも定義されています。しかし、これらは古いバージョンとの互換性を保つために用意されているもので、新しいプログラムにこれらを用いることは望ましくないです。
<>はファイルハンドルで指定されたファイルの行を順に読み出す演算子です。たとえば、以下のコードは標準入力から1行$aに読み込みます。
$a = <STDIN>;
<>;の中にファイルハンドルを書く場合、<と>;の間にはファイルハンドル以外に空白文字などがあってはなりません。たとえば以下は間違いです。
$a = < STDIN >; # 間違い
<>で読み込んだ行には改行も含まれるため、これが不要な場合はchomp演算子などを使用して切り落とします。入力ファイルの終了はeof関数で知ることができます。配列を要求するコンテキストでは<>は一度にファイル全体を読み込みます。たとえば、次のコードは標準入力から入力の終わりまでを配列aに読み込みます。
@a = <STDIN>;
この結果1行目が$a[0]に、2行目が$a[1]に...と順に格納されます。
while文およびfor文の条件式にファイルハンドルのない<>を 記述すると以下のような特別な意味になります。
たとえば、以下のスクリプトはcatコマンドと同じような動作をします。
while ( <> ) { { print; # デフォルトで$_を標準出力に出力 }
「ファイルハンドルのない<>」は複数のファイルを扱うことができます。現在使用中のファイル名は$ARGVで、使用中のファイルハンドルはARGVで参照することができます。「ファイルハンドルのない<>」 を利用するとフィルタプログラムを容易に作成することができます。
getcを使うとファイルから1文字ずつ読み込みことができます。
ファイルへの書き込みはprintおよびprintfで行います。ptintやprintfではファイルハンドルを明示的に指定することもできますが、デフォルトのファイルをselectで指定することもできます。
read、write、sysread、syswriteを使用してバイナリファイルの読み書きを行うことができます。
ファイルをコピーするにはFile::Copyモジュールのcopyメソッドを使います。このメソッドは成功すると1を、失敗すると0を返します。$!にはエラー情報が返されます。
use File::Copy; copy $src, $dest;
$srcを$destにコピーします。ファイルはファイル名で指定することも、ファイルハンドルで指定することもできます。しかしファイルハンドルを指定するとOS上の情報の損失の可能性があるらしく、ファイル名を指定する方法が推奨されるようです、
あるディレクトリ以下のファイルを再帰的にコピーすることは、File::Copy::Recursiveモジュールのrcopyメソッドを使って簡単に実現することができます。しかし、File::Copy::Recursiveモジュールはデフォルトでは組み込まれていないかもしれませんので、PPMでインストールする必要があるかもしれません。 rcopyメソッドはデフォルトではロードされないようなので、useのimportリストに加える必要があります。
use File::Copy::Recursive 'rcopy'; rcopy( source, dest );
sourceで与えたれたパス以下のファイルをdestで与えられたパスにコピーします。
以下はResource/以下のファイルをWork/にコピーします。
use File::Copy::Recursive 'rcopy'; rcopy( "Resource/", "Work/" );
以下のスクリプトは、簡単なファイル処理の例です(洗練されていませんが)。この例では、カレントディレクトリのファイルinputfileの内容を、そのまま outputfileの 名前でカレントディレクトリに出力します。
#!/usr/bin/perl # # file_demo.pl $flin = "inputfile"; $flou = "outputfile"; # 入力ファイルをオープン if ( open(HFLIN, $flin) == 0 ) { print "input file (inputfile) open error\n"; goto error; } # 出力ファイルをオープン if ( open(HFLOU, ">$flou") == 0 ) { print "output file (outputfile) open error\n"; goto error0; } while ( <HFLIN> ) { print HFLOU $_; } close HFLOU; error0: close HFLIN; error:
# ls -Rlの結果を変数に読み込む open( FI,"ls -Rl|" ) || die; @s = <FI>; close( FI ); $prefix = ""; $n = @s; foreach $a (@s) { chop( $a ); if ( $a =~ /^\./ ) { $type = "[PATH]"; $prefix = $a; $prefix =~ s/.\///; $prefix =~ s/:/\//; $prefix =~ s/^\.\///; } elsif ( $a =~ /^total/ ) { $type = "[TOTAL]"; } elsif ( $a =~ /^$/ ) { $type = "[BLANK]"; } else { $type = "[FILE]"; @field = split( /\s+/, $a ); if ( $a =~ /\.html$/ ) { @sep = split( /\//, $prefix ); $depth = @sep; print "$depth $prefix$field[8]\n"; } } }