0

So I've created a very simple Perl script to loop through everything on the C: drive and searching for things with a specific name. Now, It's giving me this error:

Can't open directory C:\ProgramData\Application Data: Invalid argument at C:\Use  
rs\Alexander\Desktop\Coding\Perl\tree.pl line 41  
Press any key to continue . . .  

Now, C:\ProgramData is a nonexistent file. (resolved) So, my question is, why is this file being opened? Here is my code:

my $dir = dir("C:\\");
my $c = 0;
recurse($dir);
sub recurse {
    my $v = 0;
    while(my $file = $_[0]->next) {
        $v++;
        next if $v < 3;
        if($file->stringify eq "Program Files") {
            print $file->stringify;
            $c++;
        }
        recurse($file) if $file->is_dir();
    }
}
print "Total: $c";

Any help is much appreciated.
Also, I am using File::Find (Not anymore) and Path::Class for this.

Rogue
  • 636
  • 8
  • 22
  • 2
    If you're using File::Find, why are you using your custom recurse() sub? It would be better if you used forward slashes instead if backslashes for the path separator. – Ron Bergin Dec 19 '14 at 22:20
  • @Ron Bergin, Why would that be better?! – ikegami Dec 19 '14 at 23:02
  • Why do you ignore the first two files of every directory (`next if $v < 3;`)? You're probably trying to skip over `.` and `..`, but that's wrong for two reasons: 1) Not all directories have `.` and `..` by the system. 2) P::C already filters them all. – ikegami Dec 19 '14 at 23:04
  • In my experience, it does not skip over . and .. Also, I am running Windows, so I go with backslashes. – Rogue Dec 20 '14 at 02:05
  • Oops, yeah, (2) is wrong, but `next if $v < 3;` is still wrong for the other reason I gave. You should use `->children` instead of `->next`. (Bonus: This switch means you'd only have one dir handle open at once, which will help you avoid running out of file handles.) – ikegami Dec 20 '14 at 05:56
  • Ah, OK. I was going off of the example found at learn.perl.org. So, children will automatically go only to files found under that directory? That's useful to know :) – Rogue Dec 20 '14 at 17:52
  • I'm having an issue when using children. Can't call method "stringify" without a package or object reference at C:\Users\Alexander\Desktop\Coding\Perl\tree.pl line 44. Apparently it thinks $file doesn't exist or something? – Rogue Dec 20 '14 at 18:01

1 Answers1

1

First of all, C:\ProgramData does exist. Configure Explorer to show hidden files, or go to a console and do dir /a c:\, and you'll see it.

The error is for C:\ProgramData\Application Data. Now, I don't have a directory by that name, but I get a similar error for C:\Config.Msi. It's flagged as a system file. It's probably best to avoid those.

You could use eval to catch the error and ignore that directory when you get the error, or you could use Win32::File to skip dircetories flagged as system files preemptively.


The calling convention is C-ish rather than Perlish.

use Win32::File qw( GetAttributes SYSTEM );

GetAttributes($qfn, my $attrs)
   or die("$^E");

if ($attrs & SYSTEM) {
   ...
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • [Deleted question] Sorry, that was a bit of a stupid question. – Rogue Dec 20 '14 at 02:09
  • So I'd still consider myself a bit new to perl. Could you give me a practical example of using eval or the Win32::File module? – Rogue Dec 20 '14 at 02:15
  • Added requested info. – ikegami Dec 20 '14 at 05:47
  • What is the purpose of the $qfn variable? Is it my file variable, or something else? I assume my $attrs is setting a variable. – Rogue Dec 20 '14 at 16:42
  • qualified file name. `$attrs` is a new variable, as you can see by the `my`. It contains the attributes after the call is made, as you can see. – ikegami Dec 20 '14 at 17:08
  • OK, I thought it was something along those lines. Now, I think I've implemented this correctly, but this is the error I get whenever I run the script: The process cannot access the file because it is being used by another process a t C:\Users\Alexander\Desktop\Coding\Perl\tree.pl line 46. – Rogue Dec 20 '14 at 17:42
  • (btw, a qualified file name doesn't need to be an absolute path. By that, I mean any path that will identify the file given the current working directory.) – ikegami Dec 20 '14 at 21:48
  • So skip directories that give you that error. Proceed on with or without a warning as your needs dictate. – ikegami Dec 20 '14 at 21:49