HELP! File Copy, Move and Rename will not work in my script!

K

kwalike57

Hello.

I have a perplexing question that seems like it should be very
simple. I have a perl script that in a nutshell, reads a directory
and then looks for a specific file naming convention which is matched
up by using a regExp that loads a variable $FILE. Once it finds this
it Connect:Directs (copies file) the file to a remote node. After
this is done I send an email notification that the file transfer
completes. My problem is that when this whole process completes, I
want to rename the $FILE to a file.done format. I do this with the
rename function normally but saying rename ($FILE, $FILEDONE). This
is not working. I can tell the script to print out the value of $FILE
and $FILEDONE and both values are correctly indicated. For example if
$FILE is FILEa.txt then $FILEDONE would be FILEa.txt.done.

So my question is, why won't my file rename properly. My script exits
with an error indicating cannot rename $FILE.

In light of this I decided to try to copy $FILE and then also tried to
move $FILE. Neither work. This script runs on a Windows box and so I
tried to manually execute the copy and move commands from the command
line and both work fine. I can rename, copy and move the file with no
problem. I am using File::Copy in my script. I have tried using the
system command to execute the copy and moves and I have tried to
manually type in the copy and moves as well in the script. I have
only tried to do this with the variable values and have not tried
executing these commands with a qualified path to the file name.

Any ideas? This seems like it should be the easiest part of the whole
process and it has taken up a bunch of time trying to get this last
element to work.

Thanks for your help!!

Karin Walike
 
J

John W. Krahn

kwalike57 said:

Your second posting of the same problem and you still have not posted
any code.

My crystal ball seems to think that you may have a problem with
directories, either incorrect names or missing completely? Possibly on
line 42?


John
 
J

J. Gleixner

kwalike57 said:
Hello.

I have a perplexing question that seems like it should be very
simple. I have a perl script that in a nutshell, reads a directory

Care to post a short example? How the heck do you expect
anyone to be able to help, if we can't see what you're doing?

[...]
So my question is, why won't my file rename properly. My script exits
with an error indicating cannot rename $FILE.
[...]

Fix your error to include why it failed and the values of the filenames
it's trying to copy/move, maybe that'll help you figure out the problem.
It's likely either you're not in the directory you think you're in or
it's a permission problem.

perldoc File::Copy

All functions return 1 on success, 0 on failure. $! will be set if an
error was encountered.
 
K

kwalike57

Your second posting of the same problem and you still have not posted
any code.

My crystal ball seems to think that you may have a problem with
directories, either incorrect names or missing completely?  Possibly on
line 42?

John

Here is the code...

#!/perl/bin/perl
#
#NewAutoConDir.pl
#Karin Walike
#12.01.07
#
#Connect:Direct process automation for server PKSW1714
#The script sleeps and wakes up to check and see if there is a file
#has been loaded to the server for Connect:Direct to customer.
#
#
#We currently have XX customers sending/receiving data to this node.
#
#Product list: xx, xx, xx, xx, xx,

use MIME::Lite;
use Cwd;
use File::Copy;

my $date=localtime();

my $dirVM="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\";
my $doneDir="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\DONE\
\";

my $FILE;
my @FILES;

my $doneExt = ".done";

my $ConDir1="D:\\tools\\'Sterling Commerce'\\'CONNECT Direct v4.1'\
\'Common Utilities'";
my $ConDir2="D:\\Prod_D\\BOP\\Scripts\\temp";
my $ConDir3="D:\\Prod_D\\BOP\\scripts\\triggerDir";

my $LOG="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_1.txt";
my $LOG2="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_2.txt";

my $LOG3="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_3.txt";
my $LOG4="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_4.txt";

my $EXCONDIR="D:\\Prod_D\\BOP\\Scripts\\temp\\ConDirVM.cmd";


open (OUT,">>$LOG");

while(1) {


# Open the directory VM

if( -d $dirVM ) {
opendir( VMDIR, $dirVM ) || die "Cannot open directory $dirVM $!";
}else{
print "Directory $dirVM does not exist. Exiting...\n";
exit;
}

# Iterate through the directory VM

opendir(VMDIR, $dirVM) || die "Cannot open directory $dirVM $!";
#open(VMDIR,"D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\VM") || die
"Cannot open directory $dirVM $!";
#open(VMDIR,'dir "D:\Prod_D\BOP\Data\SMSDATA\PCSWHSLE\VM" |') || die;

@FILES = readdir(VMDIR);

#closedir(VMDIR);

chomp (@FILES);
print "\n@FILES\n";

foreach $FILE ( @FILES ) {

if ($FILE !~ /^RU_VIRGIN_MOBILE_[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]
[0-9][0-9].*\.gz$/) {
#print "$FILE is not an EMBARQ product...\n";
goto sleeplabel;
}else{

chomp($FILE);

print "\nFile is $FILE\n";

print "\nBeginning Connect:Direct processing for VIRGIN MOBILE
customer file...\n";

print OUT "\n$date $FILE\n";

goto sleeplabel if (!$FILE);


if (file_transfer_complete($FILE)) {
print "\nFound file $FILE\n";




open(IN, "$ConDir3\\send_triggerVM.pl");
open(OUT, ">$ConDir2\\tmp_sendVM.cdp");
while (<IN>) {
if (/ConDirFile/) {
s/ConDirFile/$dirVM$FILE/;
}
print OUT $_;
}
close(OUT);
close(IN);

print "First Connect:Direct pre-processing step passed...\n";

"$ConDir2\\tmp_sendVM.cdp > D:\\Prod_D\\BOP\\scripts\\temp\\file";
sleep 10;

print "Second Connect:Direct pre-processing step passed...\n";

system $EXCONDIR || errorexit(2, "\nConnect:Direct process failed");


print "\nConnect:Direct processing for VIRGIN MOBILE customer file
completed...\n";

print OUT "\nConnect:Direct Processed for $date $FILE\n";

# Send email to notify file has been C:D to mainframe

my $machine = "PKSW1714";

my $email = '(e-mail address removed)';

my $email2 = '(e-mail address removed)';

my $subject = "Connect:Direct Processing VIRGIN MOBILE: $FILE has
been sent to VIRGIN MOBILE node VSCPFTP01";

my $body = " Hello, \n\n $FILE has been moved from $machine to
VSCPFTP01. \n\n Please contact $email2 with questions. \n\n Thanks, \n
\n IOP Connect:Direct Team\n\n";

my $server = "10.214.13.55";

my $msg = MIME::Lite->new(
From => '(e-mail address removed)',
To => '(e-mail address removed)',
Subject => $subject,
Type => 'TEXT',
Data => $body
);

#Use SMTP to send
MIME::Lite->send('smtp', $server, Timeout=>60);
sleep 30;
$msg->send;
open(OUT, ">>$LOG"); #reopen closed LOG

print "\nEmail notification of Connect:Direct transfer sent...\n";


#sleeplabel2:
print"\n\n*******Waiting for VIRGIN MOBILE file processing to
complete*******\n\n";
sleep 50;

# Rename the current process to done

chomp($FILE);

print "File is writable\n" if -w $FILE;


$FILEDONE = $FILE . $doneExt;

chomp($FILEDONE);

print "filedone=$FILEDONE\n";

#rename ("D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\
\RU_VIRGIN_MOBILE_1_20071130.007.gz", "D:\\Prod_D\\BOP\\Data\\SMSDATA\
\PCSWHSLE\\CD\\VM\\RU_VIRGIN_MOBILE_1_20071130.007.gz.done");
rename ($FILE, $FILEDONE);

#if (renamefiles($FILE)) {
print "\nFile successfully renamed: $FILEDONE\n" || errorexit(14,
"Could not rename $FILE");
#}

#move ($FILE,$FILEDONE) || errorexit(9, "Unable to move $FILE");

#copy ($FILE,$FILEDONE) || errorexit(12, "Unable to copy $FILE to
$FILEDONE");

sleeplabel:
print"\n\n*******Waiting for VIRGIN MOBILE Connect:Direct file*******
\n\n";
sleep 10;


#
# Begin Subroutines
#



#
# Sub file_transfer_complete
#
# monitor a file for size changes over a brief period
#
# parm1 - file name
# parm2 - delay in seconds (optional)
#
sub file_transfer_complete {

my $filename = shift;
my $waitTime = shift || 20;

my $sizefirst = -s $filename; # initial file size
sleep $waitTime; # wait a while

my $sizeDelta = -s $filename; #file size after wait

if( $sizeDelta == $sizefirst ) {
print "transfer complete $filename 1: $sizefirst\t2: $sizeDelta" ;
return 1;
} else {
print "transfer incomplete $filename 1: $sizefirst\t2: $sizeDelta" ;
return 0;
}
}



# Sub errorexit print error message to the log and return an error
code
#
sub errorexit {
my $returncode = shift;
my $message = shift;
open (OUT, ">>$LOG");
print OUT "\n### ERROR $returncode ### $message";
exit ($returncode);
}

# Sub Rename files to .done extension
#
sub renamefiles {

my $file1 = shift;

my $done = ".done";

my $file2 = $file1 . $done;

rename ($file1, $file2) || die "Cannot rename $file1\n";
}
}
}
}
}
 
J

John W. Krahn

It looks like my crystal ball is batting .500, correct problem, wrong
line number.

Here is the code...

#!/perl/bin/perl

You should start off with the two pragmas:

use warnings;
use strict;
#
#NewAutoConDir.pl
#Karin Walike
#12.01.07
#
#Connect:Direct process automation for server PKSW1714
#The script sleeps and wakes up to check and see if there is a file
#has been loaded to the server for Connect:Direct to customer.
#
#
#We currently have XX customers sending/receiving data to this node.
#
#Product list: xx, xx, xx, xx, xx,

use MIME::Lite;
use Cwd;
use File::Copy;

You don't appear to be using either Cwd or File::Copy?
my $date=localtime();

my $dirVM="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\";
my $doneDir="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\DONE\
\";

my $FILE;
my @FILES;

These should be declared inside the loop instead of here.
my $doneExt = ".done";

my $ConDir1="D:\\tools\\'Sterling Commerce'\\'CONNECT Direct v4.1'\
\'Common Utilities'";
my $ConDir2="D:\\Prod_D\\BOP\\Scripts\\temp";
my $ConDir3="D:\\Prod_D\\BOP\\scripts\\triggerDir";

my $LOG="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_1.txt";
my $LOG2="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_2.txt";

my $LOG3="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_3.txt";
my $LOG4="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_4.txt";

my $EXCONDIR="D:\\Prod_D\\BOP\\Scripts\\temp\\ConDirVM.cmd";

You should use the forward slash (/) instead of the backslash (\) for
path separators.
open (OUT,">>$LOG");

You should *always* verify the success of open(). You should probably
use a different name for the filehandle.
while(1) {


# Open the directory VM

if( -d $dirVM ) {
opendir( VMDIR, $dirVM ) || die "Cannot open directory $dirVM $!";
}else{
print "Directory $dirVM does not exist. Exiting...\n";
exit;
}

# Iterate through the directory VM

opendir(VMDIR, $dirVM) || die "Cannot open directory $dirVM $!";

Why open the directory twice. The whole if-else block is superfluous.
#open(VMDIR,"D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\VM") || die
"Cannot open directory $dirVM $!";
#open(VMDIR,'dir "D:\Prod_D\BOP\Data\SMSDATA\PCSWHSLE\VM" |') || die;

@FILES = readdir(VMDIR);

#closedir(VMDIR);

chomp (@FILES);

chomp() is superfluous and *may* damage valid file names.
print "\n@FILES\n";

foreach $FILE ( @FILES ) {

if ($FILE !~ /^RU_VIRGIN_MOBILE_[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]
[0-9][0-9].*\.gz$/) {
#print "$FILE is not an EMBARQ product...\n";
goto sleeplabel;

You don't need to use goto, you should use next and a continue block
instead.
}else{

chomp($FILE);

Why chomp the same variable a second time? chomp() is superfluous and
*may* damage valid file names.
print "\nFile is $FILE\n";

print "\nBeginning Connect:Direct processing for VIRGIN MOBILE
customer file...\n";

print OUT "\n$date $FILE\n";

goto sleeplabel if (!$FILE);

You don't need to use goto, you should use next and a continue block
instead. How did $FILE get modified so that it became '0' or ''?
if (file_transfer_complete($FILE)) {

One of the classic beginner mistakes. Your subroutine
file_transfer_complete is using stat() on the file names but you need
the complete path to properly stat() the file.
print "\nFound file $FILE\n";




open(IN, "$ConDir3\\send_triggerVM.pl");
open(OUT, ">$ConDir2\\tmp_sendVM.cdp");

Why are you reusing the same filehandle name that you used for the log file?
while (<IN>) {
if (/ConDirFile/) {
s/ConDirFile/$dirVM$FILE/;

You don't have to use the same regular expression twice.
}
print OUT $_;
}
close(OUT);
close(IN);

print "First Connect:Direct pre-processing step passed...\n";

"$ConDir2\\tmp_sendVM.cdp > D:\\Prod_D\\BOP\\scripts\\temp\\file";

If you had warnings enabled you would have received a warning about a
constant in void context here.
sleep 10;

print "Second Connect:Direct pre-processing step passed...\n";

system $EXCONDIR || errorexit(2, "\nConnect:Direct process failed");

Because of the relatively high precedence of the || operator the
errorexit() sub will never be called. If you fixed the precedence then
errorexit() will only be called when system() succeeded.
print "\nConnect:Direct processing for VIRGIN MOBILE customer file
completed...\n";

print OUT "\nConnect:Direct Processed for $date $FILE\n";

# Send email to notify file has been C:D to mainframe

my $machine = "PKSW1714";

my $email = '(e-mail address removed)';

my $email2 = '(e-mail address removed)';

my $subject = "Connect:Direct Processing VIRGIN MOBILE: $FILE has
been sent to VIRGIN MOBILE node VSCPFTP01";

my $body = " Hello, \n\n $FILE has been moved from $machine to
VSCPFTP01. \n\n Please contact $email2 with questions. \n\n Thanks, \n
\n IOP Connect:Direct Team\n\n";

my $server = "10.214.13.55";

$machine, $email, $email2 and $server are constants so why are they
inside the loop?
my $msg = MIME::Lite->new(
From => '(e-mail address removed)',
To => '(e-mail address removed)',

Why define variables for those strings and then not use them?
Subject => $subject,
Type => 'TEXT',
Data => $body
);

#Use SMTP to send
MIME::Lite->send('smtp', $server, Timeout=>60);
sleep 30;
$msg->send;
open(OUT, ">>$LOG"); #reopen closed LOG

If you had used a different name for the filehandle then you wouldn't
have to do this.
print "\nEmail notification of Connect:Direct transfer sent...\n";


#sleeplabel2:
print"\n\n*******Waiting for VIRGIN MOBILE file processing to
complete*******\n\n";
sleep 50;

# Rename the current process to done

chomp($FILE);

Why chomp the same variable a third time? chomp() is superfluous and
*may* damage valid file names.
print "File is writable\n" if -w $FILE;

You are using the file name only not the complete path so -w will not
find the file you want.
$FILEDONE = $FILE . $doneExt;

chomp($FILEDONE);

Again, why are you chomp()ing the file name? Do you know what chomp() does?
print "filedone=$FILEDONE\n";

#rename ("D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\
\RU_VIRGIN_MOBILE_1_20071130.007.gz", "D:\\Prod_D\\BOP\\Data\\SMSDATA\
\PCSWHSLE\\CD\\VM\\RU_VIRGIN_MOBILE_1_20071130.007.gz.done");
rename ($FILE, $FILEDONE);

You are using the file name only not the complete path so rename() will
not find the file you want.
#if (renamefiles($FILE)) {
print "\nFile successfully renamed: $FILEDONE\n" || errorexit(14,
"Could not rename $FILE");
#}

#move ($FILE,$FILEDONE) || errorexit(9, "Unable to move $FILE");

#copy ($FILE,$FILEDONE) || errorexit(12, "Unable to copy $FILE to
$FILEDONE");

sleeplabel:

You don't need to use goto, you should use next and a continue block
instead.
print"\n\n*******Waiting for VIRGIN MOBILE Connect:Direct file*******
\n\n";
sleep 10;


#
# Begin Subroutines
#

Why are you defining your subroutines *inside* the loop?
#
# Sub file_transfer_complete
#
# monitor a file for size changes over a brief period
#
# parm1 - file name
# parm2 - delay in seconds (optional)
#
sub file_transfer_complete {

my $filename = shift;
my $waitTime = shift || 20;

my $sizefirst = -s $filename; # initial file size
sleep $waitTime; # wait a while

my $sizeDelta = -s $filename; #file size after wait

You are using the file name only not the complete path so -s will not
find the file you want.
if( $sizeDelta == $sizefirst ) {
print "transfer complete $filename 1: $sizefirst\t2: $sizeDelta" ;
return 1;
} else {
print "transfer incomplete $filename 1: $sizefirst\t2: $sizeDelta" ;
return 0;
}
}



# Sub errorexit print error message to the log and return an error
code
#
sub errorexit {
my $returncode = shift;
my $message = shift;
open (OUT, ">>$LOG");

If you had used a different name for the filehandle then you wouldn't
have to do this.
print OUT "\n### ERROR $returncode ### $message";
exit ($returncode);
}

# Sub Rename files to .done extension
#
sub renamefiles {

my $file1 = shift;

my $done = ".done";

Why not use the $doneExt variable?
my $file2 = $file1 . $done;

rename ($file1, $file2) || die "Cannot rename $file1\n";

You are using the file name only not the complete path so rename() will
not find the file you want.
}
}
}
}
}

To sum up, here is the code with modifications that should work better
(*UNTESTED*):

#!/perl/bin/perl
use warnings;
use strict;
#
#NewAutoConDir.pl
#Karin Walike
#12.01.07
#
#Connect:Direct process automation for server PKSW1714
#The script sleeps and wakes up to check and see if there is a file
#has been loaded to the server for Connect:Direct to customer.
#
#
#We currently have XX customers sending/receiving data to this node.
#
#Product list: xx, xx, xx, xx, xx,

use MIME::Lite;

my $dirVM = 'D:/Prod_D/BOP/Data/SMSDATA/PCSWHSLE/CD/VM';
my $doneDir = 'D:/Prod_D/BOP/Data/SMSDATA/PCSWHSLE/CD/VM/DONE';
my $ConDir2 = 'D:/Prod_D/BOP/Scripts/temp';
my $ConDir3 = 'D:/Prod_D/BOP/scripts/triggerDir';
my $LOG = 'D:/Prod_D/BOP/Logs/ConDirLogVM_1.txt';

my $EXCONDIR = 'D:/Prod_D/BOP/Scripts/temp/ConDirVM.cmd';

my $date = localtime;
my $doneExt = '.done';
my $machine = 'PKSW1714';
my $email = '(e-mail address removed)';
my $email2 = '(e-mail address removed)';
my $server = '10.214.13.55';


open my $LOGFH, '>>', $LOG or die "Cannot open '$LOG' $!";

while ( 1 ) {
# Open the directory VM
# Iterate through the directory VM
opendir my $VMDIR, $dirVM or die "Cannot open directory $dirVM $!";
my @FILES = readdir $VMDIR;
closedir $VMDIR;
print "\n@FILES\n";
for my $FILE ( @FILES ) {
if ( $FILE !~ /^RU_VIRGIN_MOBILE_[0-9]_[0-9]{8}.*\.gz$/ ) {
#print "$FILE is not an EMBARQ product...\n";
next;
}
print "\nFile is $FILE\n";
print "\nBeginning Connect:Direct processing for VIRGIN MOBILE
customer file...\n";
print $LOGFH "\n$date $FILE\n";
next unless file_transfer_complete( "$dirVM/$FILE" );
print "\nFound file $FILE\n";
open my $IN, '<', "$ConDir3/send_triggerVM.pl" or die "Cannot
open '$ConDir3/send_triggerVM.pl' $!";
open my $OUT, '>', "$ConDir2/tmp_sendVM.cdp" or die "Cannot
open '$ConDir2/tmp_sendVM.cdp' $!";
while ( <$IN> ) {
s/ConDirFile/$dirVM$FILE/;
print $OUT $_;
}
close $OUT;
close $IN;
print "First Connect:Direct pre-processing step passed...\n";
sleep 10;
print "Second Connect:Direct pre-processing step passed...\n";
system( $EXCONDIR ) == 0 or errorexit( 2, "\nConnect:Direct
process failed" );
print "\nConnect:Direct processing for VIRGIN MOBILE customer
file completed...\n";
print $LOGFH "\nConnect:Direct Processed for $date $FILE\n";
# Send email to notify file has been C:D to mainframe
my $subject = "Connect:Direct Processing VIRGIN MOBILE: $FILE
has been sent to VIRGIN MOBILE node VSCPFTP01";
my $body = <<BODY;
Hello,

$FILE has been moved from $machine to VSCPFTP01.

Please contact $email2 with questions.

Thanks,

IOP Connect:Direct Team

BODY
my $msg = MIME::Lite->new(
From => $email2,
To => $email,
Subject => $subject,
Type => 'TEXT',
Data => $body,
);
#Use SMTP to send
MIME::Lite->send( 'smtp', $server, Timeout => 60 );
sleep 30;
$msg->send;
print "\nEmail notification of Connect:Direct transfer sent...\n";
print "\n\n*******Waiting for VIRGIN MOBILE file processing to
complete*******\n\n";
sleep 50;
# Rename the current process to done
print "File is writable\n" if -w "$dirVM/$FILE";
my $FILEDONE = $FILE . $doneExt;
print "filedone=$FILEDONE\n";
rename "$dirVM/$FILE", "$dirVM/$FILEDONE" or die "Cannot rename
'$dirVM/$FILE' to '$dirVM/$FILEDONE' $!";
print "\nFile successfully renamed: $FILEDONE\n" or errorexit(
14, "Could not rename $FILE" );
}
continue {
print "\n\n*******Waiting for VIRGIN MOBILE Connect:Direct
file*******\n\n";
sleep 10;
}
}

#
# Begin Subroutines
#

# Sub file_transfer_complete
#
# monitor a file for size changes over a brief period
#
# parm1 - file name
# parm2 - delay in seconds (optional)
#
sub file_transfer_complete {
my $filename = shift;
my $waitTime = shift || 20;
my $sizefirst = -s $filename; # initial file size
sleep $waitTime; # wait a while
my $sizeDelta = -s $filename; #file size after wait
if ( $sizeDelta == $sizefirst ) {
print "transfer complete $filename 1: $sizefirst\t2: $sizeDelta";
return 1;
}
else {
print "transfer incomplete $filename 1: $sizefirst\t2: $sizeDelta";
return 0;
}
}

# Sub errorexit print error message to the log and return an error code
#
sub errorexit {
my $returncode = shift;
my $message = shift;
print $LOGFH "\n### ERROR $returncode ### $message";
exit $returncode;
}

__END__




John
 
K

kwalike57

It looks like my crystal ball is batting .500, correct problem, wrong
line number.
Here is the code...
#!/perl/bin/perl

You should start off with the two pragmas:

use warnings;
use strict;
#
#NewAutoConDir.pl
#Karin Walike
#12.01.07
#
#Connect:Direct process automation for server PKSW1714
#The script sleeps and wakes up to check and see if there is a file
#has been loaded to the server for Connect:Direct to customer.
#
#
#We currently have XX customers sending/receiving data to this node.
#
#Product list:  xx, xx, xx, xx, xx,
use MIME::Lite;
use Cwd;
use File::Copy;

You don't appear to be using either Cwd or File::Copy?
my $date=localtime();
my $dirVM="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\";
my $doneDir="D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\\DONE\
\";
my $FILE;
my @FILES;

These should be declared inside the loop instead of here.
my $doneExt = ".done";
my $ConDir1="D:\\tools\\'Sterling Commerce'\\'CONNECT Direct v4.1'\
\'Common Utilities'";
my $ConDir2="D:\\Prod_D\\BOP\\Scripts\\temp";
my $ConDir3="D:\\Prod_D\\BOP\\scripts\\triggerDir";
my $LOG="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_1.txt";
my $LOG2="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_2.txt";
my $LOG3="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_3.txt";
my $LOG4="D:\\Prod_D\\BOP\\Logs\\ConDirLogVM_4.txt";
my $EXCONDIR="D:\\Prod_D\\BOP\\Scripts\\temp\\ConDirVM.cmd";

You should use the forward slash (/) instead of the backslash (\) for
path separators.
open (OUT,">>$LOG");

You should *always* verify the success of open().  You should probably
use a different name for the filehandle.
while(1) {
   # Open the directory VM
   if( -d $dirVM ) {
           opendir( VMDIR, $dirVM ) || die "Cannot open directory $dirVM $!";
   }else{
           print "Directory $dirVM does not exist. Exiting....\n";
   exit;
   }
   # Iterate through the directory VM
   opendir(VMDIR, $dirVM) || die "Cannot open directory $dirVM $!";

Why open the directory twice.  The whole if-else block is superfluous.
   #open(VMDIR,"D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\VM") || die
"Cannot open directory $dirVM $!";
   #open(VMDIR,'dir "D:\Prod_D\BOP\Data\SMSDATA\PCSWHSLE\VM" |') || die;
           @FILES = readdir(VMDIR);
   #closedir(VMDIR);
           chomp (@FILES);

chomp() is superfluous and *may* damage valid file names.
           print "\n@FILES\n";
   foreach $FILE ( @FILES ) {
           if ($FILE !~ /^RU_VIRGIN_MOBILE_[0-9]_[0-9][0-9][0-9][0-9][0-9][0-9]
[0-9][0-9].*\.gz$/) {
                   #print "$FILE is not an EMBARQ product...\n";
                   goto sleeplabel;

You don't need to use goto, you should use next and a continue block
instead.
           }else{
           chomp($FILE);

Why chomp the same variable a second time?  chomp() is superfluous and
*may* damage valid file names.
           print "\nFile is $FILE\n";
           print "\nBeginning Connect:Direct processing for VIRGIN MOBILE
customer file...\n";
           print OUT "\n$date $FILE\n";
           goto sleeplabel if (!$FILE);

You don't need to use goto, you should use next and a continue block
instead.  How did $FILE get modified so that it became '0' or ''?
                   if (file_transfer_complete($FILE)) {

One of the classic beginner mistakes.  Your subroutine
file_transfer_complete is using stat() on the file names but you need
the complete path to properly stat() the file.
                   print "\nFound file $FILE\n";
   open(IN, "$ConDir3\\send_triggerVM.pl");
   open(OUT, ">$ConDir2\\tmp_sendVM.cdp");

Why are you reusing the same filehandle name that you used for the log file?
   while (<IN>) {
           if (/ConDirFile/) {
           s/ConDirFile/$dirVM$FILE/;

You don't have to use the same regular expression twice.
           }
           print OUT $_;
           }
           close(OUT);
           close(IN);
   print "First Connect:Direct pre-processing step passed...\n";
   "$ConDir2\\tmp_sendVM.cdp > D:\\Prod_D\\BOP\\scripts\\temp\\file";

If you had warnings enabled you would have received a warning about a
constant in void context here.
sleep 10;
   print "Second Connect:Direct pre-processing step passed...\n";
   system  $EXCONDIR || errorexit(2, "\nConnect:Direct process failed");

Because of the relatively high precedence of the || operator the
errorexit() sub will never be called.  If you fixed the precedence then
errorexit() will only be called when system() succeeded.
   print "\nConnect:Direct processing for VIRGIN MOBILE customer file
completed...\n";
   print OUT "\nConnect:Direct Processed for $date $FILE\n";
   # Send email to notify file has been C:D to mainframe
   my $machine = "PKSW1714";
   my $email = '(e-mail address removed)';
   my $email2 = '(e-mail address removed)';
   my $subject = "Connect:Direct Processing VIRGIN MOBILE: $FILE has
been sent to VIRGIN MOBILE node VSCPFTP01";
   my $body = " Hello, \n\n $FILE has been moved from $machine to
VSCPFTP01. \n\n Please contact $email2 with questions. \n\n Thanks, \n
\n IOP Connect:Direct Team\n\n";
   my $server = "10.214.13.55";

$machine, $email, $email2 and $server are constants so why are they
inside the loop?
   my $msg = MIME::Lite->new(
           From => '(e-mail address removed)',
           To => '(e-mail address removed)',

Why define variables for those strings and then not use them?
           Subject => $subject,
           Type => 'TEXT',
           Data => $body
   );
   #Use SMTP to send
   MIME::Lite->send('smtp', $server, Timeout=>60);
   sleep 30;
   $msg->send;
   open(OUT, ">>$LOG"); #reopen closed LOG

If you had used a different name for the filehandle then you wouldn't
have to do this.
   print "\nEmail notification of Connect:Direct transfer sent...\n";
   #sleeplabel2:
   print"\n\n*******Waiting for VIRGIN MOBILE file processing to
complete*******\n\n";
   sleep 50;
   # Rename the current process to done
   chomp($FILE);

Why chomp the same variable a third time?  chomp() is superfluous and
*may* damage valid file names.
   print "File is writable\n" if -w $FILE;

You are using the file name only not the complete path so -w will not
find the file you want.
   $FILEDONE = $FILE . $doneExt;
   chomp($FILEDONE);

Again, why are you chomp()ing the file name?  Do you know what chomp() does?
   print "filedone=$FILEDONE\n";
   #rename ("D:\\Prod_D\\BOP\\Data\\SMSDATA\\PCSWHSLE\\CD\\VM\
\RU_VIRGIN_MOBILE_1_20071130.007.gz", "D:\\Prod_D\\BOP\\Data\\SMSDATA\
\PCSWHSLE\\CD\\VM\\RU_VIRGIN_MOBILE_1_20071130.007.gz.done");
   rename ($FILE, $FILEDONE);

You are using the file name only not the complete path so rename() will
not find the file you want.
   #if (renamefiles($FILE)) {
                   print "\nFile successfully renamed: $FILEDONE\n" || errorexit(14,
"Could not rename $FILE");
   #}
   #move ($FILE,$FILEDONE) || errorexit(9, "Unable to move $FILE");
   #copy ($FILE,$FILEDONE) || errorexit(12, "Unable to copy $FILE to
$FILEDONE");
   sleeplabel:

You don't need to use goto, you should use next and a continue block
instead.
   print"\n\n*******Waiting for VIRGIN MOBILE Connect:Direct file*******
\n\n";
   sleep 10;
#
# Begin Subroutines
#

Why are you defining your subroutines *inside* the loop?
#
# Sub file_transfer_complete
#
# monitor a file for size changes over a brief period
#
# parm1 - file name
# parm2 - delay in seconds (optional)
#
sub file_transfer_complete {
my $filename = shift;
my $waitTime = shift || 20;
my $sizefirst = -s $filename;      # initial file size
sleep $waitTime;           # wait a while
my $sizeDelta = -s $filename;      #file size after wait

You are using the file name only not the complete path so -s will not
find the file you want.
if( $sizeDelta == $sizefirst ) {
   print "transfer complete $filename 1: $sizefirst\t2: $sizeDelta" ;
   return 1;
} else {
   print "transfer incomplete $filename 1: $sizefirst\t2: $sizeDelta" ;
   return 0;
   }
}
# Sub errorexit print error message to the log and return an error
code
#
sub errorexit {
   my $returncode = shift;
   my $message = shift;
   open (OUT, ">>$LOG");

If you had used a different name for the filehandle then you wouldn't
have to do this.
   print OUT "\n### ERROR $returncode ### $message";
   exit ($returncode);
}
# Sub Rename files to .done extension
#
sub renamefiles {
   my $file1 = shift;
   my $done = ".done";

Why not use the $doneExt variable?
   my $file2 = $file1 . $done;
   rename ($file1, $file2) || die "Cannot rename $file1\n";

You are using the file name only not the complete path so rename() will
not find the file you want.
}
}
}
}
}

To sum up, here is the code with modifications that should work better
(*UNTESTED*):

#!/perl/bin/perl
use warnings;
use strict;
#
#NewAutoConDir.pl
#Karin Walike
#12.01.07
#
#Connect:Direct process automation for server PKSW1714
#The script sleeps and wakes up to check and see if there is a file
#has been loaded to the server for Connect:Direct to customer.
#
#
#We currently have XX customers sending/receiving data to this node.
#
#Product list:  xx, xx, xx, xx, xx,

use MIME::Lite;

my $dirVM    = 'D:/Prod_D/BOP/Data/SMSDATA/PCSWHSLE/CD/VM';
my $doneDir  = 'D:/Prod_D/BOP/Data/SMSDATA/PCSWHSLE/CD/VM/DONE';
my $ConDir2  = 'D:/Prod_D/BOP/Scripts/temp';
my $ConDir3  = 'D:/Prod_D/BOP/scripts/triggerDir';
my $LOG      = 'D:/Prod_D/BOP/Logs/ConDirLogVM_1.txt';

my $EXCONDIR = 'D:/Prod_D/BOP/Scripts/temp/ConDirVM.cmd';

my $date     = localtime;
my $doneExt  = '.done';
my $machine  = 'PKSW1714';
my $email    = '(e-mail address removed)';
my $email2   = '(e-mail address removed)';
my $server   = '10.214.13.55';

open my $LOGFH, '>>', $LOG or die "Cannot open '$LOG' $!";

while ( 1 ) {
     # Open the directory VM
     # Iterate through the directory VM
     opendir my $VMDIR, $dirVM or die "Cannot open directory $dirVM $!";
     my @FILES = readdir $VMDIR;
     closedir $VMDIR;
     print "\n@FILES\n";
     for my $FILE ( @FILES ) {
         if ( $FILE !~ /^RU_VIRGIN_MOBILE_[0-9]_[0-9]{8}.*\.gz$/) {
             #print "$FILE is not an EMBARQ product...\n";
             next;
             }
         print "\nFile is $FILE\n";
         print "\nBeginning Connect:Direct processing for VIRGINMOBILE
customer file...\n";
         print $LOGFH "\n$date $FILE\n";
         next unless file_transfer_complete( "$dirVM/$FILE" );
         print "\nFound file $FILE\n";
         open my $IN,  '<', "$ConDir3/send_triggerVM.pl" or die "Cannot
open '$ConDir3/send_triggerVM.pl' $!";
         open my $OUT, '>', "$ConDir2/tmp_sendVM.cdp"    or die "Cannot
open '$ConDir2/tmp_sendVM.cdp' $!";
         while ( <$IN> ) {
             s/ConDirFile/$dirVM$FILE/;
             print $OUT $_;
             }
         close $OUT;
         close $IN;
         print "First Connect:Direct pre-processing step passed....\n";
         sleep 10;
         print "Second Connect:Direct pre-processing step passed....\n";
         system( $EXCONDIR ) == 0 or errorexit( 2, "\nConnect:Direct
process failed" );
         print "\nConnect:Direct processing for VIRGIN MOBILE customer
file completed...\n";
         print $LOGFH "\nConnect:Direct Processed for $date $FILE\n";
         # Send email to notify file has been C:D to mainframe
         my $subject = "Connect:Direct Processing VIRGIN MOBILE: $FILE
has been sent to VIRGIN MOBILE node VSCPFTP01";
         my $body = <<BODY;
  Hello,

  $FILE has been moved from $machine to VSCPFTP01.

  Please contact $email2 with questions.

  Thanks,

  IOP Connect:Direct Team

BODY
         my $msg = MIME::Lite->new(
             From    => $email2,
             To      => $email,
             Subject => $subject,
             Type    => 'TEXT',
             Data    => $body,
             );
         #Use SMTP to send
         MIME::Lite->send( 'smtp', $server, Timeout => 60 );
         sleep 30;
         $msg->send;
         print "\nEmail notification of Connect:Direct transfer sent...\n";
         print "\n\n*******Waiting for VIRGIN MOBILE file processing to
complete*******\n\n";
         sleep 50;
         # Rename the current process to done
         print "File is writable\n" if -w "$dirVM/$FILE";
         my $FILEDONE = $FILE . $doneExt;
         print "filedone=$FILEDONE\n";
         rename "$dirVM/$FILE", "$dirVM/$FILEDONE" or die "Cannot rename
'$dirVM/$FILE' to '$dirVM/$FILEDONE' $!";
         print "\nFile successfully renamed: $FILEDONE\n" or errorexit(
14, "Could not rename $FILE" );
         }
     continue {
         print "\n\n*******Waiting for VIRGIN MOBILE Connect:Direct
file*******\n\n";
         sleep 10;
         }
     }

#
# Begin Subroutines
#

# Sub file_transfer_complete
#
# monitor a file for size changes over a brief period
#
# parm1 - file name
# parm2 - delay in seconds (optional)
#
sub file_transfer_complete {
     my $filename = shift;
     my $waitTime = shift || 20;
     my $sizefirst = -s $filename;    # initial file size
     sleep $waitTime;                 # wait a while
     my $sizeDelta = -s $filename;    #file size after wait
     if ( $sizeDelta == $sizefirst ) {
         print "transfer complete $filename 1: $sizefirst\t2: $sizeDelta";
         return 1;
         }
     else {
         print "transfer incomplete $filename 1: $sizefirst\t2: $sizeDelta";
         return 0;
         }
     }

# Sub errorexit print error message to the log and return an error code
#
sub errorexit {
     my $returncode = shift;
     my $message    = shift;
     print $LOGFH "\n### ERROR $returncode ### $message";
     exit $returncode;
     }

__END__

John

Thanks for all of the thought and advice you have put into this
response. I will give it a try and see if I get anywhere. Since this
posting I have been testing with a number of different changes, all no
good so far.

Thanks again,

Karin Walike
 
T

Tad J McClellan

kwalike57 said:
Subject: HELP! File Copy, Move and Rename will not work in my script!


[ snip over 500 lines of quoted text ]

Thanks for all of the thought and advice you have put into this
response. I will give it a try and see if I get anywhere. Since this
posting I have been testing with a number of different changes, all no
good so far.


Did we really need to see the 500 lines that your 4 lines of new text
were referring to?

Have you seen the Posting Guidelines that are posted here frequently?

You should do that soon before your posts become widely invisible...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top