Solved

pattern matching on directory names

Posted on 2000-03-02
10
246 Views
Last Modified: 2010-03-05
(this is my second week in perl, please be gentle and verbose)

I have an array of filenames built recursively on the ARGV's given like so -- movefiles.pl docs temp ftp

I'd like to be able to pull each directory (and however many nested subdirs) from each array element (while leaving the array intact).  

I have this code from another question:
@Bits = split /AA/, $filename;
foreach $Chunk (@Bits)
{
  @Create_Subdirs;
}
But I'm not looking for AA, I need to split on / -- and the compiler really doesn't like it when I do that.


# this part is just for trivia
Afterward, I want to create each dir if necessary, but is there a worse performance hit for trying to verify its existence with a
mkdir ($MoveDir, 777)
   unless (opendir VAR2, "$MoveDir");
or to just try to create the dir and fail?
0
Comment
Question by:kmarf
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
  • +2
10 Comments
 
LVL 1

Author Comment

by:kmarf
ID: 2577434
Deleted the wrong one.  
Comments first...

* I'm using ActivePerl (win32).  The posted script loops endlessly, and I'm not sure how the $TOP_LEVEL condition is met.

* All I need to know is how to grab each directory out of a file's pathname.  So, out of /temp/bla/oct/file.txt  I'd like to get /temp and /bla and /oct - because I need to create those directories elsewhere.

Here's maneshir's comments...

here is a PERL script that accepts directory names from the command line and recursively goes thru that directory and shows you the files and sub-directories.

try this script and let me know what additional functionality you are looking for, since i am not clear about your exact requirements.


====recurse.pl
#!/usr/bin/perl

$TOP_LEVEL=0;

foreach $dir (@ARGV){
  push @dir,$dir;
   
  while ($dirs=pop @dir){
    $whereami=`pwd`;
    chomp($whereami);
    chomp($dirs);
    chdir $dirs;
    print "CHANGING to $dirs\n";
       
    while (<*>) {
      next if ($_ eq ".");
      next if ($_ eq "..");
      if (-d $_) {
        next if (-l $_);
        print "\t Dir-> ",$_,"\n" if $TOP_LEVEL;
        push @dir,$dirs."/".$_;
      } else {
        print "\t File-> ",$_,"\n" if $TOP_LEVEL;
        print "\t",$_,"\n" if !$TOP_LEVEL;
      }
    }
    exit if $TOP_LEVEL;
   chdir $whereami;
  }
}


0
 
LVL 16

Expert Comment

by:maneshr
ID: 2577438
This script accepts parameters from the command prompt and recursively lists the files and the contents of files in sub-directories.

try this script & let me know your exact requirements so that i can tweak this script to produce the ouput that you need.

=============recurse.pl
#!/usr/bin/perl

$TOP_LEVEL=0;

foreach $dir (@ARGV){
  push @dir,$dir;
 
  while ($dirs=pop @dir){
    $whereami=`pwd`;
    chomp($whereami);
    chomp($dirs);
    chdir $dirs;
    print "CHANGING to $dirs\n";
     
    while (<*>) {
      next if ($_ eq ".");
      next if ($_ eq "..");
      if (-d $_) {
        next if (-l $_);
        print "\t Dir-> ",$_,"\n" if $TOP_LEVEL;
        push @dir,$dirs."/".$_;
      } else {
        print "\t File-> ",$_,"\n" if $TOP_LEVEL;
        print "\t",$_,"\n" if !$TOP_LEVEL;
      }
    }
    exit if $TOP_LEVEL;
    chdir $whereami;
  }
}
0
 
LVL 16

Expert Comment

by:maneshr
ID: 2577702
The $TOP_LEVEL variable has nothing to do with the loop condition. its just a variable i am using for debugging.

if $TOP_LEVEL is set to 1 you will see some debugging messages.


however after looking at your requirements this is what you need.

Lets say in your loop you are trapping the full path of the file in a variable....

#!/usr/local/bin/perl

$file="/temp/bla/oct/file.txt";

@dirs=split(/\//,$file); ## Split with / as the delimiter

$file_name=pop(@dirs); ## Remove the filename from the array

print $file_name,"\n";  ## Print the actual file_name

foreach(@dirs){ ## Print the individual directories
  print $_,"\n";
}


===Here is the output
file.txt

temp
bla
oct

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:PC_User321
ID: 2577865
foreach $Dir (@ARGV){
   @Parts = split m|/|, $Dir;
   $Out = "";
   foreach $Word (@Parts) {
      $Out = $Out . $Word . "/";
      print "$Out\n";
   }
}


For example, if this is called with params /u/v/wxy/z roger/ab/cd, the output will be

/
/u/
/u/v/
/u/v/wxy/
/u/v/wxy/z/
roger/
roger/ab/
roger/ab/cd/

You shoud replace the 'print' line with the action that you want to do
0
 
LVL 5

Expert Comment

by:PC_User321
ID: 2577908
foreach $Dir (@ARGV){
   @Parts = split m|/|, $Dir;
   $Out = "";
   foreach $Word (@Parts) {
      $Out = $Out . $Word . "/";
      print "$Out\n";
   }
}


For example, if this is called with params /u/v/wxy/z roger/ab/cd, the output will be

/
/u/
/u/v/
/u/v/wxy/
/u/v/wxy/z/
roger/
roger/ab/
roger/ab/cd/

You shoud replace the 'print' line with the action that you want to do
0
 
LVL 5

Expert Comment

by:PC_User321
ID: 2577918
The answer to your question about splitting on '/' is illustrated above.  Instead of using / to delimit search strings, you can use any other character, as long as you tell Perl by putting an 'm' in front.
0
 

Expert Comment

by:KuznesofAA
ID: 2580824
kmarf,

This code fragment should give you what you need:

#!/usr/bin/perl -w

#loop around each command line argument
foreach $dir (@ARGV){

  #split on "/" and create @parts array
  @parts = split(m#/#,$dir);

  #place number of array elements into $last
  $last = @parts;

  #print the last array element of $parts
  print "$parts[($last-1)]\n";
}
0
 
LVL 84

Accepted Solution

by:
ozo earned 50 total points
ID: 2580908
"$parts[-1]\n" is the same as "$parts[@parts-1]\n"

You can verify if $MoveDir is a directory with -d $MoveDir

You can
use File::Path
to create or remove a series of directories
0
 
LVL 1

Author Comment

by:kmarf
ID: 2581146
Probably I wasn't clear enough in my description of what I was looking for.

What I ended up using, however, was mkpath -- which is part of File::Path, as ozo suggested.
0
 
LVL 1

Author Comment

by:kmarf
ID: 2581170
Though the only reason none of the above comments worked for me is - I'm sure - more of a reflection on my lack of understanding of perl....
0

Featured Post

Enroll in June's Course of the Month

June’s Course of the Month is now available! Experts Exchange’s Premium Members, Team Accounts, and Qualified Experts have access to a complimentary course each month as part of their membership—an extra way to sharpen your skills and increase training.

Question has a verified solution.

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

In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
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

688 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