Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

searching files

by michael99 (Acolyte)
on Mar 05, 2020 at 02:47 UTC ( [id://11113812]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I am trying to search files which not equal "user_ABC_*.pdf" * could be anything while $user_input is specified by user. May I know how should I define the naming?

my $user_input = "user"; opendir my $dh4, $doc_dir or die "can't open directory:$!"; while (my $entry3 = readdir $dh4){ if($entry3 ne $user_input."_ABC_"*.pdf{ ...};

Replies are listed 'Best First'.
Re: searching files
by 1nickt (Canon) on Mar 05, 2020 at 04:04 UTC

    Hi, welcome to Perl, the One True Religion.

    eq and ne do not work as the solution to a problem where '* could be anything.'

    You need instead a solution where the string is compared against a pattern in which '* could be anything.' This is called a regular expression match. See perlretut for a tutorial.

    You can also play with regular expressions and see what they are doing at Your case probably wants to use a regexp like

    if ($entry3 !~ /${user_input}_ABC_\S*\.pdf/) { ... }

    ... but I would search for files using Path::Iterator::Rule myself.

    use Path::Iterator::Rule; ... my $rule = Path::Iterator::Rule->new; $rule->file->not_name( qr/${user_input}_ABC_\S*\.pdf/ ); my $next = $rule->iter( $doc_dir ); while (defined( my $file = $next->() )) { ... }

    Hope this helps!

    The way forward always starts with a minimal test.
Re: searching files
by AnomalousMonk (Archbishop) on Mar 05, 2020 at 09:23 UTC

    If you don't want to follow the advice of others concerning Path::* (and there are other modules to do similar things) and want to roll your own regex, be warned that regex be tricky.

    For instance, the  qr/${user_input}_ABC_.*pd/ regex used here fails (i.e., accepts as valid) the xyzabc_ABC_hipdip filename. (There's also the problem that the logical sense of the test is wrong, but that's minor.)

    Line-end anchors  \A \z can be useful here, as can  \Q \E metaquoting escape sequences to guard against regex metacharacters included in the  $user_input portion of the filename. E.g.:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $user_input = 'ab+c'; my $excluded = qr{ \A \Q$user_input\E _ABC_ .* [.] pdf \z }xms; ;; FILE: foreach my $file (qw( ab+c_ABC_something.pdf ab+c_ABC_anything.pdf ab+c_ABC_.pdf xab+c_ABC_.pdf ab+c_ABC_.pdfx xab+c_ABC_.pdfx abc_ABC_something.pdf abc_ABC_anything.pdf abc_ABC_.pdf abc _.pdf xyzabc_ABC_hipdip foobar )) { next FILE if $file =~ $excluded; print qq{'$file' is not excluded}; } " 'xab+c_ABC_.pdf' is not excluded 'ab+c_ABC_.pdfx' is not excluded 'xab+c_ABC_.pdfx' is not excluded 'abc_ABC_something.pdf' is not excluded 'abc_ABC_anything.pdf' is not excluded 'abc_ABC_.pdf' is not excluded 'abc' is not excluded '_.pdf' is not excluded 'xyzabc_ABC_hipdip' is not excluded 'foobar' is not excluded
    Note that the initialization of the  $user_input has been changed to  'ab+c' so as to include a regex metacharacter as an example of the effect of the  \Q \E escapes.

    Update: The quotemeta built-in can be used instead of  \Q \E escapes:
        my $user_input = quotemeta 'ab+c';
        my $excluded = qr{ \A $user_input _ABC_ .* [.] pdf \z }xms;

    Note also that thorough testing is wise in case you are using a regex approach; see Test::More and its ilk.

    Please see perlre, perlretut, and perlrequick.

    Give a man a fish:  <%-{-{-{-<

Re: searching files
by Marshall (Canon) on Mar 05, 2020 at 05:50 UTC
    You need a regular expression to match on wildcards like "*".
    Adapt this to your situation.
    The syntax is a bit weird because the letter immediately following "$user" is a word character and there has to be a way to tell where the $user variable stops and the "_ABC" begins....
    use strict; use warnings; my $user_input = "abc"; my $regex = qr/${user_input}_ABC_.*pd/; foreach my $file (qw (abc abc_ABC_something.pdf abc_ABC_anything.pdf +)) { next unless $file =~ /$regex/; print "$file is valid\n"; } __END__ abc_ABC_something.pdf is valid abc_ABC_anything.pdf is valid
Re: searching files
by clueless newbie (Curate) on Mar 05, 2020 at 14:59 UTC

    Andy Lester's ack will do that quite nicely.

    To search files NOT named ".lst" for the string ".txt":

    ack "--ignore-file=match:\.lst" "\.txt"

    Or in your case something like

    ack "--ignore-file=match:<user stuff here>_ABC_.*\.pdf" "\.txt"

    Yes, it's coded in perl.

    Yes, I'm on Windows. For *nix use 's in place of "s.

Re: searching files
by Anonymous Monk on Mar 05, 2020 at 04:08 UTC

    Use a regex of some sort...

    # Untested for file name with space. $base_name =~ m{ \A $input some-fixed-string .*? [.]pdf \z }x;

      I tried this and is working. Thank you. However, when i use -e to test it, seems not working. Could you pointed me out?

      if (-e m{ \A $input some-fixed-string .*? [.]pdf \z }x} .. }
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2024-04-16 04:46 GMT
Find Nodes?
    Voting Booth?

    No recent polls found