Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does -l $_ do in Perl, and how does it work?

Tags:

perl

What is the meaning of the nest code

foreach (@items)
{
    if (-l $_)    ## this is what I don't understand: the meaning of -l
    {
        ...
    }
}

Thanks for any help.

like image 553
adir Avatar asked Nov 30 '22 13:11

adir


2 Answers

Let's look at each thing:

foreach (@items) {
    ...
}

This for loop (foreach and for are the same command in Perl) is taking each item from the @items list, and setting it to $_. The $_ is a special variable in Perl that is used as sort of a default variable. The idea is that you could do things like this:

foreach (@items) {
    s/foo/bar/;
    uc;
    print;
}

And each of those command would operate on that $_ variable! If you simply say print with nothing else, it would print whatever is in $_. If you say uc and didn't mention a variable, it would uppercase whatever is in $_.

This is now discouraged for several reasons. First, $_ is global, so there might be side effects that are not intended. For example, imagine you call a subroutine that mucked with the value of $_. You would suddenly be surprised that your program doesn't work.

The other -l is a test operator. This operator checks whether the file given is a symbolic link or not. I've linked to the Perldoc that explains all of the test operators.

If you're not knowledgeable in Unix or BASH/Korn/Bourne shell scripting, having a command that starts with a dash just looks weird. However, much of Perl's syntax was stolen... I mean borrowed from Unix shell and awk commands. In Unix, there's a command called test which you can use like this:

if test -L $FILE
then
    ....
fi

In Unix, that -L is a parameter to the test command, and in Unix, most parameters to commands start with dashes. Perl simply borrowed the same syntax dash and all.

Interestingly, if you read the Perldoc for these test commands, you will notice that like the foreach loop, the various test commands will use the $_ variable if you don't give it a variable or file name. Whoever wrote that script could have written their loop like this:

foreach (@items)
{
    if (-l)   ## Notice no mention of the `$_` variable
    {
        ...
    }
}

Yeah, that's soooo much clear!

Just for your information, The modern way as recommended by many Perl experts (cough Damian Conway cough) is to avoid the $_ variable whenever possible since it doesn't really add clarity and can cause problems. He also recommends just saying for and forgetting foreach, and using curly braces on the same line:

for my $file (@items) {
    if ( -l $file ) {
        ...
    }
}

That might not help with the -l command, but at least you can see you're dealing with files, so you might suspect that -l has something to do with files.

Unfortunately, the Perldoc puts all of these file tests under the -X section and alphabetized under X, so if you're searching the Perldoc for a -l command, or any command that starts with a dash, you won't find it unless you know. However, at least you know now for the future where to look when you see something like this: -s $file.

like image 186
David W. Avatar answered Dec 20 '22 04:12

David W.


It's an operator that checks if a file is a symbolic link.

like image 43
ikegami Avatar answered Dec 20 '22 04:12

ikegami