2

I am using Perl. I am making an array of files inside a directory. Hidden files, ones that begin with a dot, are at the beginning of my array. I want to actually ignore and skip over those, since I do not need them in the array. These are not the files I am looking for.

The solution to the problem seems easy. Just use regular expression to search for and exclude hidden files. Here's my code:

opendir(DIR, $ARGV[0]);                             
my @files = (readdir(DIR)); 
closedir(DIR);  

print scalar @files."\n"; # used just to help check on how long the array is



for ( my $i = 0; $i < @files; $i++ )
    {
     # ^ as an anchor, \. for literal . and second . for match any following character

     if ( $files[ $i ] =~ m/^\../ || $files[ $i ] eq '.' ) #
        {
         print "$files[ $i ] is a hidden file\n";

         print scalar @files."\n";  
        }

    else
       {
         print $files[ $i ] . "\n";
       }

    } # end of for loop

This produces an array @files and shows me the hidden files I have in the directory. Next step is to remove the hidden files from the array @files. So use the shift function, like this:

opendir(DIR, $ARGV[0]);                             
my @files = (readdir(DIR)); 
closedir(DIR);  

print scalar @files."\n"; # used to just to help check on how long the array is



for ( my $i = 0; $i < @files; $i++ )
    {
     # ^ as an anchor, \. for literal . and second . for match any following character

     if ( $files[ $i ] =~ m/^\../ || $files[ $i ] eq '.' ) #
        {
         print "$files[ $i ] is a hidden file\n";
         shift @files;
         print scalar @files."\n";  
        }

    else
       {
         print $files[ $i ] . "\n";
       }

    } # end of for loop

I get an unexpected result. My expectation is that the script will:

  1. make the array @files,
  2. scan through that array looking for files that begin with a dot,
  3. find a hidden file, tell me it found one, then promptly shift it off the front end of the array @files,
  4. then report to me the size or length of @files,
  5. otherwise, just print the name of the files that I am actually interested in using.

The first script works fine. The second version of the script, the one using the shift function to remove hidden files from @files, does find the first hidden file (. or current directory) and shifts it off. It does not report back to me about .., the parent directory. It also does not find another hidden file that is currently in my directory to test things out. That hidden file is a .DS_store file. But on the other had, it does find a hidden .swp file and shifts it out.

I can't account for this. Why does the script work OK for the current directory . but not the parental directory ..? And also, why does the script work OK for a hidden .swp file but not the hidden .DS_Store file?

ES55
  • 490
  • 1
  • 5
  • 14
  • The `shift @files;` in the middle of the loop will remove **$files[0]** from the array and shift the other elements down. So what was **$files[1]** is the new **$files[0]** and so on. The `shift ...` does not work on **$files[ $i ]**, unless **$i==0**. – AdrianHHH Apr 19 '13 at 15:24

1 Answers1

6

After shifting a file, your index $i now points to the following file.

You can use grep to get rid of the files whose names start with a dot, no shifting needed:

my @files = grep ! /^\./, readdir DIR;
choroba
  • 231,213
  • 25
  • 204
  • 289
  • If you could, @choroba, could you "unpack" your line for me. That is, I am assuming that your line is streamlined in the sense that you might have taken a few simpler functions and merged them together into a single line by way of a fancier syntax. My understanding of the `grep` syntax is: `grep` [which option] . Have you simply replaced the last argument with a readdir function? Also, what is the role of the `,` between `/` and `readdir`? – ES55 Apr 19 '13 at 14:50
  • See [grep](http://p3rl.org/grep). It works as a filter: before the comma, there is a negated regular expression match. Each member of `readdir` is matched against it, and if the expression returns true, it is kept in the result. – choroba Apr 19 '13 at 14:52