lomSpace has asked for the wisdom of the Perl Monks concerning the following question:
I need to mv files from dir1(/home/mydir/dir1/RESULTS 2008) to dir2 (/home/mydir/dir2)
When I run the script stdout shows the contents of /home/mydir/dir1/RESULTS 2008. That seems to work.
What is not working is the second part where the foreach
should go through each subdir, which should be captured with @files = grep /^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/,@files;
I don't see those files. Can't mv what you can't see.
use warnings;
use strict;
# goes from current dir, and looks thru
# a subdir named 7, for subdirs starting with
# Jan_2009_, then goes into that subdir and finds
# files begiining with a or b or c
# making your particular regexes is up to you
#opendir ( my $rs, "tarfs-orion/orion/Data/Sequencing_Result<br>/RESUL
+TS 2009");
my $topdir = "/home/mgavi/testdir1/RESULTS 2008";
my @subdirs = get_sub_dirs($topdir);
my $newdir = "/home/mgavi/testdir2";
sub get_sub_dirs {
my $dir = shift;
opendir my $dh, $dir or die "Error: $!";
print "$dh\n";
my @dirs = readdir $dh;
print "@dirs\n";
@dirs = grep /^Results(.*)$/,@dirs;
closedir $dh;
return @dirs;
}
print "subdirs = @subdirs\n";
foreach my $dir(@subdirs){
opendir my $dh, "$topdir/$dir" or die "Error: $!";
my @files = readdir $dh;
print "raw files = @files\n";
@files = grep /^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/,@files;
print "$dir -> @files\n";
foreach my $file(@files){
system( "mv $topdir/$dir/$file $newdir/$file");
}
closedir $dh;
}
In need of perl wisdom
Re: mv files from dir1 to dir2
by zentara (Archbishop) on Jan 12, 2009 at 17:13 UTC
|
@files = grep /^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/,@files;
# is not doing what you think
| [reply] [d/l] |
|
Here are file name examples:
12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1
12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1,
12774L1_SD_B06_2008-12-01.ab1 12774L1_SU_A06_2008-12-01.ab1
My regex,/^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/, should capture any of these?
| [reply] |
|
Yes. But you could have answered that question yourself with a short experiment:
use strict;
use warnings;
while (<DATA>) {
if (/^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/) {
print "match: $_";
print ' $1', " is $1\n";
print ' $2', " is $2\n";
print ' $3', " is $3\n";
}
else {
print "no match: $_";
}
}
__DATA__
12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1
12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1
12774L1_SD_B06_2008-12-01.ab1
12774L1_SU_A06_2008-12-01.ab1
foo.bar
prints:
match: 12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1
$1 is 12774L1
$2 is LacZ
$3 is .SEE.rc_C06_2008-12-01.ab1
match: 12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1
$1 is 12774L1
$2 is pgK
$3 is .Neo.2fw_D06_2008-12-01.ab1
match: 12774L1_SD_B06_2008-12-01.ab1
$1 is 12774L1
$2 is SD
$3 is _B06_2008-12-01.ab1
match: 12774L1_SU_A06_2008-12-01.ab1
$1 is 12774L1
$2 is SU
$3 is _A06_2008-12-01.ab1
no match: foo.bar
Update: Furthermore, grep properly filters out the "foo.bar" file I injected:
| [reply] [d/l] [select] |
|
|
It looks to me, like your $topdir, in your script, has Results_2008 on the hardcoded path, where my script, finds Results_2008 as a subdir, as your original specification was. So you have a path_logic error.
| [reply] |
|
|
|
|
Your script with those filenames works here:
in /testdir1/Results_2008:
12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1
12774L1_SD_B06_2008-12-01.ab1
12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1
12774L1_SU_A06_2008-12-01.ab1
in /testdir1/Results_2009:
no files
My script:
#!/usr/bin/perl
use warnings;
use strict;
my $topdir = "/home/zentara/testdir1";
my @subdirs = get_sub_dirs($topdir);
my $newdir = "/home/zentara/testdir2";
sub get_sub_dirs {
my $dir = shift;
opendir my $dh, $dir or die "Error: $!";
# print "$dh\n"; #this is your glob
my @dirs = readdir $dh;
@dirs = grep /^Results(.*)$/,@dirs;
closedir $dh;
return @dirs;
}
print "subdirs = @subdirs\n";
foreach my $dir(@subdirs){
opendir my $dh, "$topdir/$dir" or die "Error: $!";
my @files = readdir $dh;
print "raw files = @files\n";
@files = grep /^(\d+\D\d)_(LacZ|pgK|SD|SU)(.*)$/,@files;
print "$dir -> @files\n";
foreach my $file(@files){
# system( "mv $topdir/$dir/$file $newdir/$file");
}
closedir $dh;
}
OUTPUT:
subdirs = Results_2008 Results_2009
raw files = . .. 12774L1_SU_A06_2008-12-01.ab1 12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1 12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1 12774L1_SD_B06_2008-12-01.ab1
Results_2008 -> 12774L1_SU_A06_2008-12-01.ab1 12774L1_pgK.Neo.2fw_D06_2008-12-01.ab1 12774L1_LacZ.SEE.rc_C06_2008-12-01.ab1 12774L1_SD_B06_2008-12-01.ab1
raw files = . ..
Results_2009 ->
You must have some overlooked spelling error in your pathnames or something?
| [reply] [d/l] |
|
|
|
|
Re: mv files from dir1 to dir2
by CountZero (Bishop) on Jan 12, 2009 at 18:51 UTC
|
Ending a regex with (.*)$ is generally quite useless.What you are saying is that after the first part of the regex, there should be something (anything at all) or nothing until the end. As it could be anything (including nothing), why bother? You can safely drop it. There is no need to anchor your regexp on both sides, esp. not with '.*'. Of course you capture the .* part but you never use the captures, so you can drop all the parentheses as well and gain a bit of speed.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] [select] |
|
| [reply] |
Re: mv files from dir1 to dir2
by gasho (Beadle) on Jan 12, 2009 at 18:40 UTC
|
use File::Find::Rule;
sub fullPathToFile #($StartDirectory,$SearchExpression)
{
my ($StartDirectory,$SearchExpression)= @_;
my(@files,$IsWin1,$IsWin2,$IsWin3,@File_Paths,$Fl,@d,$c);
@files = File::Find::Rule->file()->name("$SearchExpression")->in("
+$StartDirectory");
$IsWin1=substr($StartDirectory,1,1);
$IsWin2=substr($StartDirectory,0,2);
$IsWin3=substr($StartDirectory,0,1);
print "HO HO:$IsWin3\n";
#If $StartDirectory starts with "D:\" or "\\\\" or" \" than it
+is Win replace / with \
if( ($IsWin1 eq ':')||($IsWin2 eq '\\\\') ||($IsWin3 eq '\\')
+ )
{
foreach $Fl (@files)
{
@d=split(/\//,$Fl);
$c=join ("\\",@d);
push(@File_Paths,$c);
}
}
else
{
@File_Paths=@files;
}
return @File_Paths;
}
$LocationOfTheScriptsDirectory='/Harness/RootOfAllFiles';
$newdir='/TEST';
$SearchExp='*.abl';
@AllFilePaths=fullPathToFile($LocationOfTheScriptsDirectory,$SearchExp
+);
foreach $file (@AllFilePaths){
@A2 =split(/\//,$file);
$fileName=$A2[-1];
system( "cp $file $newdir/$fileName");
}
(: Life is short enjoy it :)
| [reply] [d/l] |
|
Not clear what this is supposed to do?
| [reply] |
Re: mv files from dir1 to dir2
by targetsmart (Curate) on Jan 13, 2009 at 13:34 UTC
|
I am not exactly replying to your problem, but recently I found that system(mv ..) couldn't give proper return status,
if we would have IGNORED the CHLD signal or improper signal handler set for CHLD.
This is because system(mv) generally forks a process and system function depends on CHLD signal internally to provide us the return status. If we ignore SIGCHLD we won't get proper return value from system function.
I have put this in interest of beginner monks.
| [reply] |
|
|