?
Solved

keeping subdirectory files in order

Posted on 2003-02-24
10
Medium Priority
?
372 Views
Last Modified: 2012-06-27
I am traversing a directory with all its subdirectories and I need to keep all the filenames grouped by directories, starting with the root, then going depth-first.  This does not automatically happen because some filenames in the root directory, for example, may alphabetically precede the subdirectories. In order to fix this, I was thinking of adding a prefix to each file, so if it's in the root, its prefix would be 001, the next folder would be 002, etc. So basically, I want it to look something like this:  "001C:\Perl\Test\Image.tif"
                      "002C:\Perl\Test\SubDir\Image.tif"
Any ideas on how to add this prefix (which I will later remove) or another way to keep the directories in order?
Thanks
 
0
Comment
Question by:njprov
  • 5
  • 4
10 Comments
 
LVL 27

Accepted Solution

by:
wilcoxon earned 150 total points
ID: 8013262
One simple way is to use nested hashes.  The directories:

C:\Perl\Test\Image.tif
C:\Perl\Test\SubDir\Image.tif

Would end up being stored as:

$hash{C}{Perl}{Test}{Image.tif} = 1 (or some other value)
$hash{C}{Perl}{Test}{SubDir}{Image.tif} = 1

-or-

$hash{C}{Perl}{Test}{_files} = ['Image.tif', etc]
$hash{C}{Perl}{Test}{SubDir}{_files} = ['Image.tif', etc]

Or I'm sure you could come up with other some other method.
You could also keep an array of arrays for quick depth counts.

$depth[2] = ['C:\Perl\Test', etc]
$depth[3] = ['C:\Perl\Test\SubDir', etc]
0
 
LVL 5

Expert Comment

by:PC_User321
ID: 8015055
use File::Find;
$directory = ".";   # (or whatever)

sub wanted
{
    print "Found $File::Find::dir   $_\n"  unless (-d);
}

find(\&wanted, $directory);
0
 
LVL 27

Expert Comment

by:wilcoxon
ID: 8016421
I'm pretty sure File::Find returns things in physical storage order within the directory, doesn't it?  Physical storage order is usually not alphabetically ordered (unless you're on Windows with FAT32 and just ran Norton SpeedDisk or similar).

If that is the case, then the files returned by File::Find will not be ordered (one of niprov's requirements).
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:njprov
ID: 8017663
Thanks, these are good ideas.  As far as the File::Find, I can't seem to use it. In fact, I can't get past the "use File::Find;" line, I get:

File/Find.pm in @INC at test.pl line 1

Is this a version problem, am I missing some libraries? I'm a Perl beginner so please bear with me. Thanks!
0
 

Author Comment

by:njprov
ID: 8017701
Sorry, that should be:

Can't locate File/Find.pm in @INC at test.pl line 1

0
 
LVL 27

Expert Comment

by:wilcoxon
ID: 8018419
Hmm.  What version of perl are you using (perl -V should tell you)?

File::Find should be part of the core modules.  I'm not sure with what version it was added though.
0
 

Author Comment

by:njprov
ID: 8018812
it's version 5.001
0
 
LVL 27

Expert Comment

by:wilcoxon
ID: 8018960
Ah.  That is a very old version of perl.  I am fairly sure File::Find was not part of the core at that point.

If you have the option, you might want to seriously consider upgrading to a more recent perl - 5.005_03 (the last before 5.6), 5.6.1 (5.6.0 was buggy), or 5.8.0 are good candidates.
0
 

Author Comment

by:njprov
ID: 8019110
it's version 5.001
0
 

Author Comment

by:njprov
ID: 8019440
Thank you for your help. I don't know why we are using an old version, I'll find out about that. Meanwhile, I wrote my own function which takes care of the alphabetical problem by processing each file in a directory first, before going into the next directory. Here is the code, in case someone runs into a similar problem.

my($root) = "C:\\Perl\\Test";
DoDir($root);

sub DoDir
{
   my($dir) = shift;
   my($file);
   opendir(DIR, $dir) || die "Unable to open $dir :$!";
   my(@files) = grep {!/^\.\.?$/ } readdir(DIR);
   closedir(DIR);
   foreach (@files)
   {
      if (-f ($file = "$dir\\$_"))
      {
      #process the file here  
      print "Found a file: $file\n";
      }
   }
   foreach (@files)
   {
      if (-d ($file = "$dir\\$_"))
      {
         print "Found a directory: $file\n";
         DoDir($file);
      }

   }
}
0

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question