# The Universe of Discourse

Fri, 21 Mar 2008

        my $command = shift; for my$file (@ARGV) {
if ($file =~ /\.gz$/) {
my $fh; unless (open$fh, "<", $file) { warn "Couldn't open$file: $!; skipping\n"; next; } my$fd = fileno $fh;$file = "/proc/self/fd/$fd"; } } exec$command, @ARGV;
die "Couldn't run command '$command':$!\n";

When the loop exits, \$fh is out of scope, and the filehandle it contains is garbage-collected, closing the file.

"Duh."

Several people suggested that it was because open files are not preserved across an exec, or because the meaning of /proc/self would change after an exec, perhaps because the command was being run in a separate process; this is mistaken. There is only one process here. The exec call does not create a new process; it reuses the same one, and it does not affect open files, unless they have been flagged with FD_CLOEXEC.

Abhijit Menon-Sen ran a slightly different test than I did:

        % z cat foo.gz bar.gz
cat: /proc/self/fd/3: No such file or directory
cat: /proc/self/fd/3: No such file or directory

As he said, this makes it completely obvious what is wrong, since the two files are both represented by the same file descriptor.