Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

How can I readdir and ! -d in one line

by misterperl (Pilgrim)
on Oct 27, 2020 at 16:08 UTC ( [id://11123216]=perlquestion: print w/replies, xml ) Need Help??

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

I need to readdir non-dot files, and non-directory files. I have :
die "oh snap\n" unless opendir D, $myDir; my @Fx = grep /^\w/,readdir I; closedir I; for ( @Fx ) { next if -d "$myDir/$"; push @F,$_; }
which gets the job done, @F is correct, but its so wordy!

Can I use a ! -d "$myDir/$" somehow in the readdir line with the grep to do all my filtering at once?

TY wise ones.

Replies are listed 'Best First'.
Re: How can I readdir and ! -d in one line
by Fletch (Bishop) on Oct 27, 2020 at 16:14 UTC

    grep can take a BLOCK with multiple tests and/or you can just use and and chain multiple checks (recommended best practice is to use the BLOCK form rather than the EXPR form these days anyhoo). Or use something like File::Find::Rule rather than lower level primitives.

    my @F = grep { /^\w/ and not -d "$myDir/$_" } readdir( I );

    Edit: Path::Tiny is another possibility.

    use Path::Tiny; my @files = grep !$_->is_dir, path( $myDir )->children( qr/^\w/ );

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

      Ahh well crafted my friend, another ++ vote.. It occurs to be in linux I might PIPE the result to ! -d or something , but I don't know about any Perl pipe.

      TYVM

        A perl equivalent (of sorts) might be to chain greps on different conditionals, but (IMHO) that's not particularly clearer in this case than simply having the one predicate step check both conditions (not-dir and starts with a wordchar) at the same time.

        my @files = grep { ! -d qq{$myDir/$_} } grep { /^\w/ } readdir( I );

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

Re: How can I readdir and ! -d in one line
by haukex (Archbishop) on Oct 28, 2020 at 21:17 UTC

    Personally I prefer Path::Class:

    use Path::Class qw/dir/; my @files = sort grep { !$_->is_dir && $_->basename=~/^[^.]/ } dir($path)->children;

    Alternatively, a core-only way to do it is:

    use File::Spec::Functions qw/ no_upwards catfile catdir /; opendir my $dh, $path or die "$path: $!"; my @files = sort map { catfile($path,$_) } grep { ! -d catdir($path,$_) && /^[^.]/ } no_upwards readdir $dh; closedir $dh;
Re: How can I readdir and ! -d in one line
by BillKSmith (Monsignor) on Oct 28, 2020 at 01:53 UTC
    You can use an OO approach. Create a subclass of IO::Dir which returns only the files you want. This probably is slightly longer than what you already have, but it separates the special code from your application. (And it would be available for reuse)
    Bill
Re: How can I readdir and ! -d in one line
by Anonymous Monk on Oct 27, 2020 at 19:52 UTC
    Find rule is cake, readdir is flour

    use File::Find::Rule qw/ find rule / ; my @dirs = find( directory => maxdepth => 1, name => qr/\w/, )->in($startdir);

Re: How can I readdir and ! -d in one line
by Anonymous Monk on Oct 27, 2020 at 19:33 UTC

      Please provide example code showing how one can accomplish the OP's aim using File::Find "or any of its many brethren".

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11123216]
Approved by Paladin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-03-29 08:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found