Solved

pattern matching on directory names

Posted on 2000-03-02
10
239 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
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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Perl output collect 7 69
Add additional column to .csv using Perl. 8 165
Convert grep lines to perl 6 80
Insert Text into odbc.ini file 15 71
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…
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…

726 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