?
Solved

pattern matching on directory names

Posted on 2000-03-02
10
Medium Priority
?
250 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 150 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

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…
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
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

765 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