What is _ (single underscore) in Perl without $ or @?
I have some code like this:
if (!-d _ || !-o _ || ($vncUserDirUnderTmp && ($mode & 0777) != 0700)) {
raise Exception("$prog: Wrong type or access mode of $vncUserDir.\n")
}
I could find information about @_
and $_
in Perl but not about _
alone.
What does it mean in -d _
and -o _
here?
When used with a filetest (-X) operator the stat
structure of the previous file test is used
If any of the file tests (or either the
stat
orlstat
operator) is given the special filehandle consisting of a solitary underline, then thestat
structure of the previous file test (orstat
operator) is used, saving a system call.
...
Example:stat($filename); print "Readable\n" if -r _; print "Writable\n" if -w _; ...
So in your example !-d _
tests whether the file last stat
-ed isn't a directory.
Update
The unusual _
is really a typeglob *_
but with operators expecting a filehandle the *
may be omitted, like <*STDIN>
may be written as <STDIN>
. It is found in the symbol table
print *{$main::{_}}{IO}, "\n"; # --> IO::Handle=IO(0x2311970)
In a one-liner the *_
gets set up only after calls to stat
and _
are made.
When you call one of the file test operators (-f
, -d
, -s
, etc) Perl actually makes a call to the operating system's stat
function. The stat
function returns a structure full of all sorts of interesting information about the file in question, but each of the file test operators only looks at one of the fields from that structure (is it a file? is it a directory? how big is it?)
It's common that you might want to know more that one piece of information about a file (is it a file? can I read it? can I execute it?) The naive way to write that is:
if (-f $file and -r $file and -x $file)
But that makes three calls to stat
- with each one of them only looking at one of the fields from the structure. To mitigate that, Perl is clever and caches the results of the most recent call to stat
. It is cached against the special filehandle _
. So a more efficient way to write the same code is:
if (-f $file and -r _ and -x _)
That only makes one call to stat
.
Since Perl 5.10, you can also use "stacked file tests" and write this code as:
if (-x -r -f $file) # Note reversed order of operators
Update: perldoc says this about stacked file operators.
As of Perl 5.10.0, as a form of purely syntactic sugar, you can stack file test operators, in a way that
-f -w -x $file
is equivalent to"-x $file && -w _ && -f _
. (This is only fancy syntax: if you use the return value of-f $file
as an argument to another filetest operator, no special magic will happen.)