Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

file test results not as expected

by navalned (Sexton)
on Nov 21, 2020 at 22:44 UTC ( #11123993=perlquestion: print w/replies, xml ) Need Help??

navalned has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to push all executibles in my $PATH to an array, but doesn't seem to work as expected.

use IO::Dir; my @cmds; my @paths = split /\:/, $ENV{PATH}; foreach my $path (@paths) { tie my %dir, 'IO::Dir', $path; foreach my $file (keys %dir) { if (-f -x $file) { push @cmds, $file; } } undef %dir; } foreach my $cmd (@cmds) { print $cmd . "\n"; }

Here is the output I'm getting:


I guess its kinda cool it found a perl related executable, but I was hoping for more.

Replies are listed 'Best First'.
Re: file test results not as expected
by toolic (Bishop) on Nov 21, 2020 at 23:33 UTC
    You need to use the full path to the file for the file test. Change:
    if (-f -x $file) {
    if (-f -x "$path/$file") {

    This is how I do it: Finding commands in Unix PATH:

    findcmd is a script which searches through the directories in the Unix PATH variable for executable files

      Thats cool and works well. You can try this for a 5 sec improvement at least on my system:

      grep { -x "$path/$_" && !-d _ }

      Saves a lot of stat() calls.

      Thanks for the answer. I think I knew the answer deep in the recesses of my brain but couldn't see it.

Re: file test results not as expected
by Fletch (Chancellor) on Nov 22, 2020 at 03:13 UTC

    Using Path::Tiny

    $ perl -MPath::Tiny -E 'for my $dir ( split(/:/,$ENV{PATH}) ){say for +grep {-f -x $_} path($dir)->children }'

    Also depending on your shell it may already have these cached. For instance ZSH provides a commands hash which maps from the command name to the corresponding file name.

    $ print -l "${(@k)commands}" | sort | tail zipinfo zipnote zipsplit zless zmore znew zprint zsh zsh-5.8 $ print $commands[zsh] /usr/local/bin/zsh

    Edit: Dump the ZSH cache with for i in "${(@onk)commands}" ; { printf "%20s\t%s\n" "$i" "$commands[$i]" } | less; of course keep in mind that the commands parameter shows only what would be found first on PATH; if you're looking for exhaustive (including things with matching names shadowed in subsequent directories) you'd want the other solutions.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11123993]
Approved by toolic
Front-paged by toolic
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2020-12-03 07:12 GMT
Find Nodes?
    Voting Booth?
    How often do you use taint mode?

    Results (51 votes). Check out past polls.