in reply to Re^7: Restrict file search within current filessystem using wanted subroutine
in thread Restrict file search within current filessystem using wanted subroutine

Hi Hauke,

I tried excluding a specific file (say /var/log/test.out) as below:

return if ($File::Find::name =~ test.out);

This seems to work. but this might exclude test.out if it finds in any other filesystem. so tried to use the below code but doesn't work.

return if ($File::Find::name =~ /^\/var\/log\/lastlog);

Whats the best way to exlcude test.out from /var/log?

  • Comment on Re^8: Restrict file search within current filessystem using wanted subroutine

Replies are listed 'Best First'.
Re^9: Restrict file search within current filessystem using wanted subroutine
by haukex (Archbishop) on May 17, 2016 at 20:34 UTC

    Hi Anonymous,

    The issue is that if you tell your script to search a relative pathname (such as the default "."), then $File::Find::name will not be an absolute pathname either. Have a look at the Basic debugging checklist - this tells you that you should print your values, such as print $File::Find::name;, and you can find this out for yourself.

    One way to fix this: 1. At the top of your script, add "use File::Spec::Functions qw/rel2abs/;" (see the function rel2abs in File::Spec), and 2. replace "shift || '.'" with "rel2abs(shift || '.')" - now all your search paths and therefore $File::Find::name should be absolute pathnames.

    If it's just that one specific file, a regex is not necessary and you can use an exact match to exclude it: return if $File::Find::name eq '/var/log/test.out';

    Hope this helps,
    -- Hauke D

    (P.S. I'm assuming that it's obvious that the regex /^\/var\/log\/lastlog/ won't help in excluding a file named test.out and that you just got your examples mixed up.)

      Hi Hauke,

      As suggested, it is good to use an exact match to exclude specific file.

      return if $File::Find::name eq '/var/log/test.out';

      But now if I want to exclude more than one file, can I use an OR condition to the above line. Else for every exclusion I have to write a new exclusion as below:

      return if $File::Find::name eq '/var/log/test.out'; return if $File::Find::name eq '/var/log/new.out';

      Regards, Madparu

        Hi Madparu,

        For exact matches you could use a hash. Before your call to find add: my %EXCLUDES = map {$_=>1} ( '/var/log/test.out', '/var/log/new.out', ); and change your condition to return if $EXCLUDES{$File::Find::name};. The first piece of code builds a hash from a list of strings, where the keys of the hash are the strings and the values are just 1, and then the condition checks to see if a hash entry with the key $File::Find::name exists and has a true value. An alternative might be to switch back to regex matches, e.g. return if $File::Find::name =~ m{^/var/log/(?:test|new)\.out$};

        Considering that I've been writing your script for you piece by piece, now might be a good time to invest some time into learning more about Perl. Have a look at perlintro, Getting Started with Perl, http://learn.perl.org/ or perhaps the books Learning Perl or Modern Perl (the latter is free). And if you run into questions or trouble, of course feel free to ask here - see How do I post a question effectively?

        Hope this helps,
        -- Hauke D