On Dec 1, 1:47 am, [EMAIL PROTECTED] wrote: > Sorry to plop so much shabby code up here but I think I've stared at > this a little too long and am now incapable of catching my error. > > This started out as just a helper script to help solve this problem: > > Needing to cp files with number names from one directory to another. > Sometimes there might be some numbered files already in the target > directory. So the problem was really two fold. > > 1) Find the right files to copy by specific content. > > I'm doing this job with grep -rl, it seems to be the fastest by > a hefty margin, to compile a list of the right files. > > 2) Once the list is compiled, copy the files over to a new directory > making sure not to clobber possible exisiting files. > > I'll probably try to turn the perl script into something more general > that does the whole job eventually if this chore looks like it might > recur enough. > > So (2) is all this script was meant to do at this point. > > The script does the job and appears to run error free. But after the > work is done I attempt to report 2 things. The number of files copied > and the number of files now in the Target. > > The second count is consistently wrong by a wide wide margin and I > am too blind to see why. > > Here is a sample run (code encluded at the end) running the script > the way it was intended to be used (script.pl TargetDir SourceList): > > ./cpNoClobber.pl test3 SourceList > > <16> Files copied to: > /home/reader/News/agent/nntp/news.gmane.org/gmane/comp/lang/perl/test3 > > <17> files now in: > /home/reader/News/agent/nntp/news.gmane.org/gmane/comp/lang/perl/test3 > > Now lets look at the results of `ls' on the target: > > ls test3/[0-9]*|wc -l > 336 > > The script gets numbering right with no clobbers I think, but the reporting > is way wrong. > > =====* Code *===== =====* Code *===== =====* Code *===== > > ./cpNoClobber.pl > > #!/usr/local/bin/perl -w >
# The following lines are your friend use strict; use warnings; > if(!$ARGV[1]){ > usage(); > print "Too few arguments.. exiting\n"; > exit; > > } > > if($ARGV[2]){ > usage(); > print "Too many arguments... exiting\n"; > exit;} > > use Cwd; > my $Cwd = getcwd; > > use File::Copy; > Define variables in the smallest scope Plus only define variables you use, otherwise it can get confusing > my ($HiNum, $Copied, $TrgDir, @DirContent, $Cnt, $Line); > $TrgDir = shift; > $HiNum = 0; > $Copied = 0; > #Use lexical file and directory handles: opendir my $DIR, $TrgDir or die "can't opendir $TgtDir: $!; > opendir(DIR,$TrgDir) or die "can't opendir $TrgDir: $!"; > > ## Find out if target directory has any numbered files in it. > ## If it does get the highest number in there To declare in smallest scope: my @DirContent = grep { /^[0-9]/ } readdir($DIR); > @DirContent = grep { /^[0-9]/ } readdir(DIR); This test add nothing. The for loop will fail if there is no content > if ($DirContent[0]){ > for(@DirContent){ Do these files only contain numbers? > if($_ > $HiNum){ > $HiNum = $_; > } > } > > } > > ## If we already have numbered files, Start our counter with > ## the highest one > if($HiNum){ > $Cnt = $HiNum; > > } > > while(<>){ > chomp; > $Cnt++ ; > ## The first if clause here is unnecessary now... to be removed > if($TrgDir){ > ## Add the correct path if our line doesn't start with '/' Use different delimiters if searching for a slash( also add some whitespace e.g. if ( !#^/#) > if(!/^\//){ > $Line = $Cwd ."/". $_; > } > if($TrgDir !~ /^\//){ > $TrgDir = $Cwd."/".$TrgDir; > } > ## Do what we came here for: copy the target files into target > ## directory with fnames that won't clobber any existing filenames > copy($Line,$TrgDir. "/". $Cnt) or die "can't copy $Line to <$TrgDir>: > $!"; > $Copied++; > } > > } > > ## Report how many files were copied > print " <$Copied> Files copied to:\n $TrgDir\n\n"; > print " ".CountTrgDir()."\n"; should be closedir($DIR); > close(DIR); > > sub CountTrgDir { > my $DirCnt = 0; > ## Recount the TargetDir The main problem, I believe, is that you are using a stale directory handle. closedir (in main) and opendir here. > @DirCnt = grep { /^[0-9]+/ } readdir(DIR); > > ## Just in case there was something wrong with my technique using > ## the array to get a count.. also tried the formulation commented out > ## below to see the actual count as it happened... still wrong > # @DirCnt = grep { /^[0-9]+/&& print "Counting <". $DirCnt++.">\n" } > readdir(DIR); > return "<".(@DirCnt + 1)."> files now in:\n $TrgDir\n"; > > } > use File::Basename; > sub usage { # use this line to get the name of your script # perldoc File::Basename my ( $myscript ) = fileparse( "$0", "" ); > print <<EOM; > > Purpose: To copy files from a list on disk to the directory of choice. > Numbering them with nonClobber names as we go (even if some > numbered files are already in the directory). > Usage: \`$myscript TARGETDIRECTORY SOURCEFILE' > (DIRECTORY= name of target directory) > NOTE: SOURCEFILE is likely to have been compiled like this: > grep -rl 'REGEX' SOMEDIRECTORY >SOURCEFILE (where SOMEDIRECTORY > is a directory full of email or posts. We are looking to skim > off those with REGEX placing the filenames in SOURCEFILE, and > copy them to another directory using \`$myscript ', so as to leave > mail or news directory unharmed. > > EOM > > } Made a few comments in the code. None of them tested - off the top of my head. HTH, Ken -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/