Filehandles, files, directories

open#

Associate a filehandle with a file, a command, or an in-memory scalar.

open is the primary way a Perl program acquires a filehandle. The three-argument form — open $fh, MODE, EXPR — is the one to use in new code: the mode is stated explicitly, the filename cannot be reinterpreted as a shell pipeline, and leading or trailing whitespace in EXPR is preserved verbatim. The older two-argument form exists for compatibility and for the “magic” filename interpretation it enables; do not feed it untrusted input.

Synopsis#

open my $fh, "<",  $path           or die "read $path: $!";
open my $fh, ">",  $path           or die "write $path: $!";
open my $fh, ">>", $path           or die "append $path: $!";
open my $fh, "+<", $path           or die "rw $path: $!";
open my $fh, "<:encoding(UTF-8)", $path or die $!;
open my $mem, ">",  \$buf          or die $!;   # in-memory
open my $pipe, "-|", "ls", "-la"   or die $!;   # read from cmd
open my $pipe, "|-", "gzip", ">$f" or die $!;   # write to cmd

What you get back#

1 on success; undef on failure, with $! set to the OS error. For the pipe forms (|- / -|), the successful return value is the pid of the child process — useful when you need to waitpid on it later. After a one- or two-argument pipe open on the literal command -, open returns twice (parent gets the child pid, child gets 0); use defined($pid) or // to distinguish the two.

Always check the return value. A failed open leaves the filehandle closed, and every subsequent read or write on it will set $! to Bad file descriptor and emit a warning under use warnings.

open my $fh, "<", $path
    or die "open $path: $!";

Global state it touches#

  • $! — set on failure to the OS-level error.

  • ${^OPEN} — default I/O layers installed by the open pragma or the -CioD switch. These apply only when MODE in the three-argument form contains no explicit layer; a bare < or > honours them, <:raw or any other explicit layer suppresses them.

  • $^F — highest file descriptor not marked close-on-exec; the new fd inherits the close-on-exec flag based on this.

  • Selected filehandle via select — unchanged by open, but becomes relevant the moment you print to the new handle without naming it.

  • For pipe forms, $? and ${^CHILD_ERROR_NATIVE} are set when the handle is later closed.

Modes#

The second argument names an I/O role. The common cases:

Mode

Meaning

fopen(3) equivalent

<

read

r

>

write, truncate or create

w

>>

append, create if missing

a

+<

read and write, no truncation

r+

+>

read and write, truncate first

w+

|-

pipe to command (we write)

-|

pipe from command (we read)

<&, >&, <&=, >&=

dup or fdopen an existing handle

Newly created files get permissions 0666 & ~umask. +< is almost always what you want for read-write; +> clobbers the file first.

I/O layers attach after the mode: <:encoding(UTF-8), >:raw, >>:crlf, <:encoding(UTF-8):crlf. An explicit layer suppresses ${^OPEN} defaults; a lone colon (<:) falls back to the OS default (:raw on Unix, :crlf on Windows).

Examples#

Read a UTF-8 text file line by line:

open my $fh, "<:encoding(UTF-8)", "notes.txt"
    or die "open notes.txt: $!";
while (my $line = <$fh>) {
    chomp $line;
    # ... use $line ...
}
close $fh or warn "close: $!";

Write a binary file with no encoding translation:

open my $out, ">:raw", "image.bin"
    or die "open image.bin: $!";
print $out $bytes;
close $out or die "close: $!";

In-memory filehandle — print into a scalar, useful for capturing output that expects a real handle:

my $buf = "";
open my $mem, ">", \$buf or die $!;
print $mem "hello\n";
close $mem;
# $buf now contains "hello\n"

Read from a command, list form so arguments are not subject to shell metacharacter interpretation:

open my $ls, "-|", "ls", "-la", $dir
    or die "ls: $!";
while (<$ls>) { print }
close $ls;                     # $? holds the exit status

Temporary anonymous file — pass undef as the third argument with a read-write mode, then seek back to the start to read what you wrote:

open my $tmp, "+>", undef or die $!;
print $tmp "scratch data\n";
seek $tmp, 0, 0;
my $line = <$tmp>;

Edge cases#

  • Two-argument “magic” open: open $fh, $name honours leading <, >, >>, a trailing |, and strips surrounding whitespace from $name. Fine for a literal filename you typed yourself; never for a filename that came from user input, the network, or an environment variable. Use the three-argument form.

  • Two-argument -: open $fh, "<-" or open $fh, "-" opens STDIN; open $fh, ">-" opens STDOUT. Three-argument equivalents are open $fh, "<", "-" and open $fh, ">", "-".

  • Reopening STDOUT / STDERR: close them first, then reopen against the new target. open STDOUT, ">", \$buf redirects all subsequent print STDOUT output into $buf.

  • Bareword filehandles (open FH, ...) are package globals and are disabled under use v5.36 or later via the bareword_filehandles feature. Prefer a lexical scalar.

  • Layers and ${^OPEN}: any explicit layer, even :, disables the defaults from the open pragma. If you rely on a pragma default, omit the colon entirely (<, not <:).

  • Pipe to a command with shell metacharacters: the two-argument pipe form (open $fh, "|cat -n | lpr") runs through /bin/sh -c. The three-argument list form (open $fh, "|-", "cat", "-n") does not and is the safer default.

  • In-memory scalar strings: treated as octet strings. Without truncation, the scalar may not contain code points above 0xFF.

  • Automatic close on scope exit: a lexical filehandle closes when its refcount hits zero, but the implicit close does not report errors. For files you wrote to, close explicitly and check the return value.

  • open vs sysopen: open wraps fopen(3) semantics with PerlIO layers on top. For direct open(2) flags like O_EXCL or O_NOFOLLOW, use sysopen.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • close — release a filehandle; check its return value for buffered writes and pipe commands

  • sysopen — open with raw open(2) flags when you need O_EXCL, O_NOFOLLOW, or similar precision

  • binmode — push or replace I/O layers on an already open handle

  • read — fixed-size byte reads from the handle open returned

  • readline — record-at-a-time reads (what <$fh> calls)

  • fileno — the underlying OS file descriptor, for flock, select, or fcntl

  • $! — OS error set when open returns undef