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/


Reply via email to