ディレクトリ操作1
■この章で解説する組み込み関数
opendir, readdir, closedir
■この章でできること
・ディレクトリ内のファイル一覧を取得する
・ファイルとディレクトリの区別をする
・ファイルテスト演算子を使う

 ディレクトリをオープンして、ディレクトリ内のファイルの一覧を取得するには、opendir、readdir、closedir関数を使います。では、まずはサンプルソースから見てみましょう。

#!/usr/bin/perl

#############################################
# ディレクトリ操作のサンプル1
# Author: "Perl Programming Tips"
#############################################

# ディレクトリオープン
opendir(HDIR, "./") or die($!);

# ディレクトリエントリの取得
@dirent = readdir(HDIR);
foreach(@dirent)
{
    print "[F]:$_\n" if (-f $_);
    print "[D]:$_\n" if (-d $_);
    print "[L]:$_\n" if (-l $_);
}

# ディレクトリクローズ
closedir(HDIR);

 実行結果は次のようになります。

[g@630m temp]$ perl file04_01.pl
[D]:.
[D]:..
[F]:file01_01.log
[F]:file01_01.pl
[F]:file01_01.txt
[F]:file02_01.log
[F]:file02_01.pl
[F]:file02_01.txt
[F]:file02_02.log
[F]:file02_02.pl
[F]:file02_02.txt
[F]:file02_03.log
[F]:file02_03.pl
[F]:file02_03.txt
[F]:file03_01.log
[F]:file03_01.pl
[F]:file03_01.txt
[F]:file04_01.pl
[D]:temp
[g@630m temp]$

 カレントディレクトリをオープンして、中に入っているファイルとディレクトリの一覧を取得して、表示しています。まず、ディレクトリをオープンするために、opendir関数を使います。

opendir
ディレクトリをオープンする。
書式
opendir dirhandle, directory
引数
dirhandle:
ディレクトリハンドル
directory:
オープンするディレクトリ
戻り値
成功した場合真、失敗した場合偽。

 opendirの第一引数には、ディレクトリハンドルを指定します。ファイルハンドルと同じように、以降のディレクトリの操作はこのディレクトリハンドルを指定して行います。なお、ディレクトリハンドルはファイルハンドルとは独立した名前空間を持っています。

 ディレクトリエントリを取得するには、readdir関数を使います。

readdir
ディレクトリからディレクトリエントリを取得する。
書式
readdir dirhandle
引数
dirhandle:
ディレクトリハンドル
戻り値
スカラーコンテキストでは次のディレクトリエントリ、リストコンテキストでは残りの全てのエントリを返す。

 readdir関数をリストコンテキストで使用すれば、一度に全部のディレクトリエントリが取得できるので便利です。なお、ディレクトリエントリを1つずつ取得する方法については、ディレクトリ操作2を参照してください。

 さて、ディレクトリエントリには、オープンしたディレクトリの直下にあるファイルとサブディレクトリが混在しています。このほかに、カレントディレクトリを表す「.」と、親ディレクトリを表す「..」も取得されます。

 これらを区別したい場合、例えばファイル一覧だけを取得したいような場合は、ファイルテスト演算子を使います。上のサンプルプログラムでは、ファイルかどうかをテストする「-f」や、ディレクトリかどうかをテストする「-d」を使っています。これらがファイルテスト演算子です。以下にファイルテスト演算子の種類を示します。

演算子
意味
-r
実効uid/gidで読み出し可
-w
実効uid/gidで書き込み可
-x
実効uid/gidで実行可
-o
実効uid/gidが所有
-R
実uid/gidで読み出し可
-W
実uid/gidで書き込み可
-X
実uid/gidで実行可
-O
実uid/gidが所有
-e
ファイルが存在する
-z
ファイルの長さが0である
-s
ファイルの長さが0ではない(サイズをバイト単位で返す)
-f
普通のファイルである
-d
ディレクトリである
-l
シンボリックリンクである
-p
名前付きパイプ(FIFO)である
-s
ソケットである
-b
ブロックスペシャルファイルである
-c
キャラクタスペシャルファイルである
-t
ファイルハンドルがttyに対してオープンされている
-u
setuidビットがセットされている
-g
setgidビットがセットされている
-k
stickyビットがセットされている
-T
テキストファイルである
-B
バイナリファイルである(-Tとは逆の意味)
-M
修正されてからの日数(実行開始時を基準とする)
-A
最後にアクセスされてからの日数(実行開始時を基準とする)
-C
inodeが変更されてからの日数(実行開始時を基準とする)

 ファイルテスト演算子は、一見すると何かのオプションのように見えますが、ちゃんとした単項演算子です。

 最後に、使い終わったディレクトリハンドルは、closedir関数でクローズします。

closedir
ディレクトリハンドルをクローズする。
書式
closedir dirhandle
引数
dirhandle:
ディレクトリハンドル
戻り値
なし

 ここではディレクトリの中のファイル一覧を取得しましたが、ディレクトリの中を再帰的に検索して、ファイルやディレクトリの一覧を取得したい場合は、File::Findモジュールを使うと簡単です。詳しくはファイルの検索1を参照してください。