Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How do I recursively create a directory tree/filesystem?

by fensterblick (Initiate)
on Jul 21, 2002 at 23:38 UTC ( [id://183899]=perlquestion: print w/replies, xml ) Need Help??

fensterblick has asked for the wisdom of the Perl Monks concerning the following question: (directories)

I would like to create a directory tree up to a certain "depth". This directory tree has sub directories, and those sub directories have even more subdirectories, all up to a certain depth.

I've spent half of the day trying to do this recursively, but for some reason, only the first directory of each level has subdirectories.

FYI, here is a stripped down version of the code I have:
#!/usr/bin/perl -w use Cwd; sub MakeDirs($$$) { #my $current_dir = getcwd(); my($base, $num_dirs, $depth) = @_; #if depth = 0, no more subdirectories need to be created if($depth == 0) { return 0; } #change the directory chdir $base; #Create directories on the current level my $dir_name = "a"; for($x = 0; $x < $num_dirs; $x++) { mkdir $dir_name; $dir_name++; } #recurse over subdirectories $dir_name = "a"; for($x = 0; $x < $num_dirs; $x++) { MakeDirs($dir_name, $num_dirs, $depth-1); $dir_name++; } return 0; } MakeDirs("/hpq/", 2, 3);
I would use File::Recurse, but the files/directories haven't been created yet. Thanks for any suggestions. This script is driving me crazy!

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I recursively create a directory tree/filesystem?
by rob_au (Abbot) on Jul 22, 2002 at 02:56 UTC
    For a more simple solution, you may want to look at the mkpath function exported from the File::Path module that is part of the core installation. Alternatively, if you are looking at writing your own function for educational purposes, you might want to look at this thread where I contributed (based on an earlier post from mirod) a more portable solution using File::Spec using a loop over the path components rather than employing recursion (Recursion makes it very easy to write bad code - Whenever I see recursive code my first urge is to refactor immediately :-).

    The code ...

    sub create_dirs { use File::Spec; my $file = shift; my $dir; foreach ( File::Spec->splitdir( (File::Spec->splitpath( $file ))[1 +] ) ) { $dir = File::Spec->catdir($dir, $_); next if -d $dir; mkdir( $dir ) || die $!; } }
     

      That's not exactly what the program was intended to do. It appears to attempt to create a directory tree, where each directory contains two more directories (a and b) to a depth of three directories. mkpath would work, but it would have to be fed a list of directories that would probably most easily be generated by recursion.
Re: How do I recursively create a directory tree/filesystem?
by Ionitor (Scribe) on Jul 22, 2002 at 00:30 UTC
    The major problem here is that you're using chdir and not returning to the right directory afterwards. Since you're changing the directory of the program, the recursion doesn't work. The fastest way to fix the problem is to add chdir '..'; before return 0;. There's a couple of other changes you might want to make described below, one of which is to avoid chdir entirely.
Re: How do I recursively create a directory tree/filesystem?
by lemming (Priest) on Jul 22, 2002 at 18:09 UTC
    For the recursive mkpath solution: Of course reading the docs helps.
    use strict; use warnings; use File::Path; my $name = shift; my $branch = shift; my $depth = shift; # We really should be checking arguments # Bad things happen if $branch or $depth is 0 print "Creating directory ",$name," with ", $branch, " branches to the depth of ", $depth, "\n"; my $aref = MkTree($name, $branch, $depth, [] ); foreach my $path ( @$aref ) { print $path, "\n"; } mkpath($aref, 1, 0777); exit; sub MkTree { my ($name, $branch, $depth, $aref) = @_; my $start = "a"; foreach my $pos (1..$branch) { my $let = chr(ord($start) + $pos - 1); if ( $depth == 1 ) { push(@$aref, join('/', $name, $let) ); } else { MkTree( join('/', $name, $let), $branch, $depth-1, $aref); } } return $aref; }
Re: How do I recursively create a directory tree/filesystem?
by Anonymous Monk on Aug 14, 2002 at 11:35 UTC

    I'm fairly new to all this so if anyone has pointers for my script please speakup.

    My solution was to use the glob() function and loop through the results looking for the next set if directories. I guess you could count the number of times the loop is run to limit the depth or you could have a target directory to stop and break out of the loop.

    The purpose of this script is to make links to all the files it finds. It is a helpful script to convert files from one system to another where users have comeup with crazy files names. Hope this helps.

    #!/usr/bin/perl -w #Do Not run as Root, this may cause dirs to be link and corrupt the; #file system; my $start; my @in; my @big; my @next; my $level; my $dir; my @files; my $file; my $z=0; my $target; print "\n\n ***********************************\n"; print "This script will create (symbolic) links recursively\n"; print "to all files in the specifiled directory and also create\n"; print "the links from the directory specified\n"; print " ***********************************\n\n"; print " Please enter the starting target directory\n"; print " (don't end with a slash)\n"; $start=<STDIN>; chomp $start; print " \nEnter the working dir where you would like\n"; print " the links to be placed?\n"; print " (don't end with a slash)\n"; $target=<STDIN>; chomp $target; @in = (glob("$start*/")); @big = (@in); do { @next = (@in); @in = (); foreach $level (@next) { @in = (@in, (glob("$level*/")))} @big = (@big, @in); @next = ();} while $in[0]; foreach $dir (@big) { @files = (@files, (glob("$dir*"))); } foreach $file (@files) { $z=$z+1; $link = "$target"."/"."$z"; print "$z \-\- $file\n"; # to creat a symbolic link change link to symlink; link("$file","$link") || warn "can't link to file $file\n"; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://183899]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-26 02:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found