ファイル名が EXPR
で指定されるファイルを open
し、
FILEHANDLE
と結び付ける。
FILEHANDLE
が expression の場合は、
その値が実際のファイルハンドルの名前として用いられる。
EXPR
を省略した場合、
FILEHANDLE
と同名のスカラー変数がファイル名を持つ。
-
ファイル名が `<' で始まるか何も付いていない場合は
ファイルは入力用に
open
される。 -
`>' で始まる場合は出力用に
open
される。
-
`>>' で始まる場合は 追加用に
open
される。
-
`>' や `<' の前に `+' を付けると
ファイルに対し
read
および write
両方の許可を得ることができる。 -
ファイル名が `|' で始まる場合はコマンドであると解釈され、
出力がそのコマンドにパイプされる。
-
ファイル名が `|' で終わる場合もコマンドであると解釈され、
そのコマンドから入力がパイプされる。
(入力・出力両方をパイプするコマンドは必要ないであろう。)
-
`-' は
STDIN
を open
し、
`>-' は STDOUT
を open
する。
成功すれば non-zero を返し、そうでない場合は undefined を返す。
open
がパイプを含む場合、返り値はサブプロセスの pid
になる。
$article = 100;
open article || die "Can't find article $article: $!\n";
while (<article>) { ...
open(LOG, '>>/usr/spool/news/twitlog');
# (log は予約語である)
open(article, "caesar <$article |");
# 記事を decrypt する
open(extract, "|sort >/tmp/Tmp$$");
# $$ は現在のプロセス #
# 引数のファイルリストについて
# それがインクルードするファイルも含めて処理する
foreach $file (@ARGV) {
do process($file, 'fh00'); # no pun intended
}
sub process {
local($filename, $input) = @_;
$input++; # これは文字列のインクリメントである
unless (open($input, $filename)) {
print STDERR "Can't open $filename: $!\n";
return;
}
while (<$input>) { # 間接指定に注意
if (/^#include "(.*)"/) {
do process($1, $input);
next;
}
... # whatever
}
}
Bourne shell
の慣習で、EXPR
を `>&' で始めても良い。
この場合、残りの文字列は ファイルハンドル
(または数値ならば ファイルディスクリプタ)と解釈され、
dup
され、open
される。
`&' は `>', `>>', `<',
`+>', `+>>', `+<' の後で用いて良い。
指定するモードは元のファイルハンドルと同じでなければならない。
以下のスクリプトは STDOUT
および STDERR
を保存し、
リダイレクトし、元に戻す。
#!/usr/bin/perl
open(SAVEOUT, ">&STDOUT");
open(SAVEERR, ">&STDERR");
open(STDOUT, ">foo.out") || die "Can't redirect stdout";
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
select(STDERR); $| = 1; # バッファリングなしにする
select(STDOUT); $| = 1; # バッファリングなしにする
print STDOUT "stdout 1\n"; # これはサブプロセスでも
print STDERR "stderr 1\n"; # 働く
close(STDOUT);
close(STDERR);
open(STDOUT, ">&SAVEOUT");
open(STDERR, ">&SAVEERR");
print STDOUT "stdout 2\n";
print STDERR "stderr 2\n";
コマンド `-' を用いてパイプを open
する場合、
すなわち `|-' または`-|' の場合、
暗黙の内に fork
がなされ、
open
の返り値は親プロセスでは子プロセスの pid
、
子プロセスでは 0 になる。
(open
が成功したかどうかは defined($pid)
で確かめる。)
ファイルハンドルの挙動は親プロセスでは通常と同じであるが、
そのファイルハンドルへの i/o は
子プロセスの STDOUT
/STDIN
にパイプされる。
子プロセスではファイルハンドルは open
されていない ---
i/o は新たな STDOUT
から/STDIN
に なされる。
良く使われるのは、例えば setuid
で走らせているときなど、
パイプコマンドの実行状態をコントロールしたい時や、
シェルコマンドにメタキャラクターがあるかどうかをチェックしたくない時である。
次の 2 つのペアはそれぞれある程度(more or less)同等である。
open(FOO, "|tr '[a-z]' '[A-Z]'");
open(FOO, "|-") || exec 'tr', '[a-z]', '[A-Z]';
open(FOO, "cat -n '$file'|");
open(FOO, "-|") || exec 'cat', '-n', $file;
明示的にパイプされたファイルハンドルを close
すると
親プロセスは子プロセスが終了するのを待ち、status 値 $?
が返り値となる。
注意:
fork
を行う操作においては、
フラッシュされていないバッファは両方のプロセスにおいてフラッシュされずに残る。
つまり、二重に出力されるのを避けるには、
$|
をセットしなければならない。See section $| : write または print の後にフラッシュを行うか否か for $|
.
open
に渡されるファイル名は最初や最後のスペースを取り除かれる。
名前におかしな文字が含まれるファイルを open
するには、
次のようにして前後のスペースが取り除かれないようにしなければならない。
$file =~ s#^(\s)#./$1#;
open(FOO, "< $file\0");