ディレクトリ操作2
■この章で解説する組み込み関数
telldir, seekdir, rewinddir
■この章でできること
・ディレクトリエントリを1つずつ取得する
・ディレクトリ内の現在位置を取得する
・ディレクトリ内をシークする
・ディレクトリの先頭に戻る

 ディレクトリ操作1では、ディレクトリ内のファイルやディレクトリの一覧を一括で取得する方法を解説しました。ここでは、ディレクトリ内のファイル名を1つずつ取得する方法を解説します。

 ディレクトリ内のエントリを取得するにはreaddir関数を使いますが、これをスカラーコンテキストで評価すると、エントリが一つだけ返ります。このようにしてreaddir関数を繰り返し呼び出せば、ディレクトリエントリを1つずつ取得することができます。

 また、現在のreaddirの位置を取得するにはtelldir関数、readdir関数で読み込む位置を指定したところにシークしたい場合はseekdir関数、ディレクトリの先頭に戻したい場合はrewinddir関数を使います。

 では、これらの関数を使ったサンプルです。

#!/usr/bin/perl

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

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

# ディレクトリエントリの取得(1-3)
&read_dir();

# readdir位置の取得
$pos = telldir(HDIR);

# ディレクトリエントリの取得(4-6)
&read_dir();

# readdir位置のシーク
seekdir(HDIR, $pos) or die($!);

# ディレクトリエントリの取得(4-6)
&read_dir();

# readdir位置を先頭に戻す
rewinddir(HDIR) or die($!);

# ディレクトリエントリの取得(1-3)
&read_dir();

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

sub read_dir
{
    # ディレクトリエントリの取得
    for ($i = 0; $i < 3; $i++)
    {
        $dirent = readdir(HDIR);
        
        print "[F]:$dirent\n" if (-f $dirent);
        print "[D]:$dirent\n" if (-d $dirent);
    }
    print "\n";
}

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

[g@630m temp]$ perl file05_01.pl
[D]:.
[D]:..
[F]:file01_01.log

[F]:file01_01.pl
[F]:file01_01.txt
[F]:file02_01.log

[F]:file01_01.pl
[F]:file01_01.txt
[F]:file02_01.log

[D]:.
[D]:..
[F]:file01_01.log
[g@630m temp]$

 最初に、サブルーチンread_dirでディレクトリエントリを3つ取得しています。その後telldir関数でディレクトリ位置を保存しておき、もう一度read_dirでディレクトリエントリを3つ取得しています。

 今度は、seekdir関数で先ほど取得したディレクトリ位置に戻り、また同じエントリを3つ取得しています。最後に、rewinddir関数でディレクトリの先頭に戻り、最初の3つのエントリをもう一度取得しています。

 実行結果を見ると、ディレクトリエントリをシークしながら取得しているのがわかります。

 それでは、各関数の詳細です。まずはtelldir関数です。この関数は、readdirで取得するディレクトリエントリの現在の位置を返します。ここで取得した位置はseekdir関数で使うことができます。

telldir
ディレクトリハンドルの現在のreaddir位置を返す。
書式
telldir dirhandle
引数
dirhandle:
ディレクトリハンドル
戻り値
ディレクトリ位置

 ディレクトリをシークするにはseekdir関数を使います。

seekdir
ディレクトリハンドルに対して、readdirを行う位置を設定する。
書式
seekdir dirhandle, pos
引数
dirhandle:
ディレクトリハンドル
pos:
シークするディレクトリ位置
戻り値
成功した場合は1、失敗した場合は未定義値

 readdirで読み込むディレクトリ位置を先頭に戻すにはrewinddir関数を使います。

rewinddir
ディレクトリハンドルに対して、readdirを行う位置を先頭に設定する。
書式
rewinddir dirhandle
引数
dirhandle:
ディレクトリハンドル
戻り値
成功した場合は1、失敗した場合は未定義値

 注意点として、readdirをサポートしているマシンでも、telldir、seekdir、rewinddirがサポートされていないこともあります。これらの関数を使う場合は、使用するマシンでサポートされていることを確認したほうがよいでしょう。