Solved

pattern matching on directory names

Posted on 2000-03-02
10
207 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
  • 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
 
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
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

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 …
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…
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…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

746 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now