The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> Perl Programming
|
Making subdirectories
Discuss Making subdirectories in the Perl Programming forum on Dev Shed. Making subdirectories Perl Programming forum discussing coding in Perl, utilizing Perl modules, and other Perl-related topics. Perl, the Practical Extraction and Reporting Language, is the choice for many for parsing textual information.
|
|
 |
|
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

July 31st, 2012, 06:27 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
|
Making subdirectories
Hi,
I have a directory (with bunch of subfolders) on the network.
I’d like to make same folder/subfolders on a local drive.
I can find all the folder/subfolders but I cannot make them on a local drive.
Could you help me please?
Thanks, testerV
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Find;
my $localdrive = 'D:' ;
my $netw_dir = "H:\\TSCB\\Docs";
sub all_subdirs {
my $subdir = $File::Find::name;
return unless -d $subdir;
return if ( $subdir eq $netw_dir);
$subdir =~s{\/}{\\}g ;
my @subdir = split/\\/, $subdir ;
shift @subdir ;
unshift @subdir, $localdrive ;
my $modifsubdir = join "\\", @subdir ;
print "$modifsubdir\n" ;
}
find (\&all_subdirs, $netw_dir);
|

August 1st, 2012, 01:10 AM
|
 |
Contributed User
|
|
|
|
Well you didn't post your attempt at making the directories.
Use make_path
FWIW, Perl won't care that you substituted / for \
Use XCOPY
Quote:
/t : Copies the subdirectory structure (that is, the tree) only, not files. To copy empty directories, you must include the /e command-line option. |
This command and option just clones the tree structure.
|

August 1st, 2012, 06:25 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
Hi Salem,
I tried “make_path”, I know it is supposed to work but it does not.
I’m missing something, it does not re-create all the sub directories.
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Path ;
my $old_dir = "C:\\P_test" ;
my $new_dir = "D:\\P_test" ;
mkpath([$old_dir, $new_dir], 1, 0777) || die "\n\Couldn't copy $old_dir '$!'";
I cannot use xcopy, it is external module and I cannot install external module.
Thanks, testerV
|

August 2nd, 2012, 05:07 AM
|
 |
Contributed User
|
|
|
|
|
> I tried “make_path”, I know it is supposed to work but it does not.
...
> mkpath([$old_dir, $new_dir]
It seems to me you used mkpath, not make_path
Plus, what is "[$old_dir, $new_dir]" supposed to be?
|

August 2nd, 2012, 02:58 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
Hi Salem,
Thank you for helping me, I really appreciate it!
As you see my skills in programming not that good, I’m working on it.
I need to keep in sync network Dir (bunch of subdirs) and a local Dir, it is not possible to add any new modules to the Perl.
My script scans the Network Dir and if any new subDirs created it recreates it on a local drive then it finds new files on the network Dir but it does not want to copy new files to the local Dirs.
Here is the script:
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Path ;
my $localdrive = 'D:' ;
my $old_dir = "H:\\TSCB\\Docs" ; ## Network Dir ##
my $new_dir = "D:\\TSCB\\Docs" ; ## Local Dir ##
my $cmd = "xcopy $old_dir $new_dir /t /e /i "; ## Keeping in sync Network and local dir ##
system ("start $cmd") or die "'$cmd' failed: $!";
my $todayday = localtime (time);
my $log = 'D:\\TSCB\\DocsTest_F3.txt' ; ## Log for any new files found ##
my $dir = "H:\\TSCB\\Docs";
open my $log_fh, '>>', $log
or die "can't open '$log' in append mode <$!>";
print $log_fh "$todayday\n" ;
find (\&find_files, $dir) ;
sub find_files {
if (-M -f $File::Find::name <1) { ## scaning for a new files ##
my $file_find_name = $File::Find::name ;
$file_find_name =~s{\/}{\\}g ;
print "$file_find_name\n" ;
my @file_find_name = split/\\/, $file_find_name ;
shift @file_find_name ;
unshift @file_find_name, $localdrive ; ## replacing "H" netdir drive with "D" local drive##
pop (@file_find_name) ; ## removing the file name from the string ##
my $modif_file_find_name = join"\\",@file_find_name ;
print "$modif_file_find_name\n" ;
print $log_fh "$file_find_name\n\n" ;
print $log_fh "$modif_file_find_name\n" ;
my $cmd2 = "xcopy $file_find_name $modif_file_find_name " ; ## trying to copy new files to the ##
system ("start $cmd2") or die "'$cmd2' failed: $!"; ## local drive but it does not work ##
}
}
close $log_fh ;
exit ;
|

August 2nd, 2012, 03:27 PM
|
|
|
|
What is preventing you from installing modules?
|

August 2nd, 2012, 03:35 PM
|
|
|
The proper solution to this problem is to use rsync, which can be done with or without the Perl script.
If you don't want to use rsync, then there are a couple other Perl solutions. If you only want to copy/duplicate a directory structure, then the File::Path module would be the most logical approach. However, if you need to also copy the files within each of the directories, then it would be better to use File::Copy::Recursive.
File::Rsync
File::Copy::Recursive
|

August 2nd, 2012, 07:01 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
|
I might be wrong but it seems to me both File::Rsync and File::Copy::Recursive are the external modules.
Can't locate File/Copy/Recursive.pm in @INC (@INC contains: C:/Perl64/site/lib C:/Perl64/lib .)
|

August 2nd, 2012, 08:00 PM
|
|
|
I don't see why you're going through all these contortions with perl and various modules.
What's wrong with a simple batch file? From your description, this should solve your problem:
Code:
rem save this as some_name.bat
xcopy H:\TSCB\Docs D:\TSCB\Docs /E /Y
(and would have solved your problem 7 posts ago if you had clicked the link salem posted)
__________________
sub{*{$::{$_}}{CODE}==$_[0]&& print for(%:: )}->(\&Meh);
|

August 2nd, 2012, 08:26 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
Thank you Omega!
Yes, I could make same batch and run it but I'm learning Perl and I'd like to write a script that will do the same thing.
make_path does not copy all the subdirs from the "Docs"folder. I'm doing something wrong just do not know what it is.
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Path qw(make_path) ;
make_path('H:\\TSCB\\Docs', 'D:\\TSCB\\Docs', {
verbose => 1,
mode => 0711,
})or die $! ;
exit ;
|

August 2nd, 2012, 09:12 PM
|
|
|
I see. The problem is that make_path doesn't do copying at all, it takes a list of directories and creates them:
Quote: | Originally Posted by perldoc File::Path The make_path function creates the given directories if they don't exists before, much like the Unix command mkdir -p.
The function accepts a list of directories to be created. Its behaviour may be tuned by an optional hashref appearing as the last parameter on the call. |
To use make_path, you'll need to assemble a list of every directory you want it to create. You might do that by pushing the directories found by File::Find into an array, then supplying that to make_path.
To save you to trouble of munging the paths in the wanted sub, here's a trick:
Code:
# Assume a directory structure like
# parent
# +-- child
# +--- file
chdir '\parent';
find( { wanted => sub { print $_; }, no_chdir => 1 }, 'child' );
With the "no_chdir" option, $_ will include a full path not just the filename and it will base those paths with respect to the relative path the "child" based on the current directory "parent". E.g., you'll get $_ = "child\file" making it assemble a path rooted in a different directory.
|

August 2nd, 2012, 11:52 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
Thank you Omega!
I found a perl script, changed it little bit and it copies my directory now. I do not understand few lines :
Code:
for $list(0..$#dirs)
($ndir."\\".$dirs[$list])
($dir."\\".$dirs[$list])
But the rest of it works.Now I need to copy all updated files from the Network dir to the local dir. Any idea how I can do that?
Thanks, testerV
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Copy;
use File::Find;
use File::Path qw(make_path) ;
my $netDir = q{H:\TSCB\Docs};
my $locDir = q{D:\TSCB\Docs};
&myDirTofind($netDir);
exit 0;
sub myDirTofind {
my ($dir) = @_;
my (@dirs,$list);
opendir(DIR,$dir) || warn "can't open the directory $dir: $!\n";
@dirs=grep {!(/^\./) && -d "$dir\\$_"} readdir(DIR);
closedir (DIR);
for $list(0..$#dirs) {
mkdir ($locDir) unless -d $locDir;
my $ndir = $dir;
$ndir =~ s"O:\\T2000\\Scripts"C:\\T2000\\Scripts";
make_path ($ndir."\\".$dirs[$list]);
&myDirTofind($dir."\\".$dirs[$list]); }
return 1;
}
exit ;
|

August 3rd, 2012, 08:21 PM
|
|
|
|
I must assume that you didn't even look at either if the 2 modules I pointed out and linked to. The File::Copy::Recursive module will copy the directory structure and files without having to use your myDirTofind() sub.
|

August 6th, 2012, 05:41 PM
|
|
Contributing User
|
|
Join Date: Jun 2012
Posts: 65
Time spent in forums: 14 h 35 m 42 sec
Reputation Power: 1
|
|
Hi Fish,
I do not have that much knowledge to ignore you or Omega.
Anyway, I tried it (see my replies ):
Code:
use File::Copy::Recursive qw(dircopy) ;
my $netDir = 'H:\\TSCB\\Docs';
my $locDir = 'D:\\TSCB\\Docs';
dircopy($netDir,$locDir) or die $!;
I got error:
Code:
Can't locate File/Copy/Recursive.pm in @INC (@INC contains: C:/Perl64/site/lib C:/Perl64/lib .)
I assumed this is an external module. It is not possible to install any modules on these machines.
Thanks, testerV
|

August 7th, 2012, 08:50 AM
|
|
|
|
The reason you gave me in your PM why you can't install modules is a bit weak.
1) You could build an install script that checks for missing dependencies and installs them as needed.
2) If the non core modules are pure Perl, as is the case with File::Copy::Recursive, you could simply include it as part of your app.
3) You could use PAR::Packer or a 3rd party app such as perl2exe to package your app and all required non core modules as a standalone executable and deploy that single executable.
4) If none of the above options are acceptable, then perl is the wrong language to use for your app. You should use a language that compiles its source code to binary executables.
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|