dgraham
(Fresh Scripter)
2006-08-10 10:15 PM
Verify succesful copy in a loop

I was hoping someone can help me with this script. I am using several other peoples UDFs to make a script that will copy files from USB thumb drives, rename them to the current data and time, and then delete the originals from the device. Everything is working perfectly, but the problem is that I am using a "For Each" statement and I can't figure out how to verify that the files are being copied BEFORE deleting the originals. Because it is a loop, I am only receiving the error code returned for the LAST file copied. If there are 4 files and the first three fail, but the last one succeeds, then the script will happily continue and delete the originals. I need some way to make the script stop if an error is detected. I had a file get lost yesterday because the workstation lost network connectivity during the transfer. The script just kept going and purged all the files on the thumbdrive. Any suggestions would be greatly appreciated. Here is the pertinent part of the script. The whole thing is very long and wont fit here. I am using the DirPlus UDF written by Bryce (I think).
Code:
  
;=======================================================================
; Copy files
;=======================================================================

;Call the Dirplus UDF.
Call @SCRIPTDIR + "\DirPlus.udf"
;
;Enumerate all FILES on drive x:
$Files = DirPlus(@SCRIPTDIR,'/S /F WMA')
;
;Split the date on the / character and the join the parts with no separation characters.
$Date = Join(Split(@Date,'/'),"")
;
;Get the filename without the drive letter so start counting at the 4th character.
$Filename = SubStr ($File, 4)
;
;Get the extension of the file.
$Ext = SubStr ($Filename, Len($Filename) - 4)
;
;Do the stuff inside the For each--next loop for each file found.
For Each $File in $Files
If $File
;Split the time at the : character and then join the parts with no separation characters.
$Time = Join(Split(@TIME,':'),"")
;Copy the file and rename it during the copy process.
Copy $File 'X:\$StringUsername\' + $Date + '-' + $Time + '.WMA'
LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
;Sleep 1 second to get the $Time var different for each file.
Sleep 1
EndIf
Next

$Error = @ERROR

If $Error = "-1"
$Msg = MessageBox ("There were no files found on the recorder","ERROR")
Quit
EndIf

If $Error = "3"
$Msg = MessageBox = ("The path was not found. There may have been a network connectivity problem." +
" Please try again. If you continue to have trouble, please call the Helpdesk.","Error")
Quit
EndIf

If $Error > 3
$Msg = MessageBox = ("Error number: " + $Error + " An unknown error has occurred. Please try again." +
" If you continue to have trouble, please call the Helpdesk.","Error")
Quit
EndIf

If $Error <> "0"
$Msg = MessageBox ("Error number: " + $Error + " An unknown error has occurred. Please try again." +
" If you continue to have trouble, please call the Helpdesk.","Error")
Quit
EndIf

If $Error = "0"
$Msg = MessageBox ('Your files have been successfully copied to" +
" the X:\'+ $StringUsername + ' folder.','File Copy Result')
EndIf


;=======================================================================
; Clean Up
;=======================================================================
Copy "\\ServerName\netlogon\Update.exe" @SCRIPTDIR /h /r
Copy "\\ServerName\netlogon\Upload Audio Files.exe" @SCRIPTDIR /r
Use W: /Del
Del @SCRIPTDIR+'\DSS_FLDA\*.*' /c
Del @SCRIPTDIR+'\DSS_FLDB\*.*' /c
Del @SCRIPTDIR+'\DSS_FLDC\*.*' /c
Del @SCRIPTDIR+'\DSS_FLDD\*.*' /c
Del @SCRIPTDIR+'\DSS_FLDE\*.*' /c
Del @SCRIPTDIR+'\DSS_FLDF\*.*' /c



Mart
(KiX Supporter)
2006-08-10 10:59 PM
Re: Verify succesful copy in a loop

You could add this after the copy command. This way the script will show the error code and text on the screen, sleep for 5 seconds and then exit so it will not deleted the stuff on the USB drive because then things obviously would be fubared.

Code:

If @ERROR
?"Eeks. Some kind of error occurred while copying: " $file
?@ERROR
?@SERROR
Sleep 5
Exit
EndIf



Richard H.Administrator
(KiX Supporter)
2006-08-11 09:57 AM
Re: Verify succesful copy in a loop

You have a number of choices depending on what you want to do:

  • Inside your loop, after each copy check the error value and delete the file if the copy was successful. This will leave individual files that caused an error on the source.
  • Inside your loop, after each copy check the error value and set your own error variable if an error occurred. After the loop check your own error variable and if set do not delete the files. In this case if an error occurs *ALL* files will be left on the source, including any which copied successfully.


Which method you opt for will be determined by your needs.


dgraham
(Fresh Scripter)
2006-08-14 05:08 PM
Re: Verify succesful copy in a loop

I added the following lines to the loop and that seems to be working.
Code:

;Do the stuff inside the For each--next loop for each file found.
For Each $File in $Files
If $File
;Split the time at the : character and then join the parts with no separation characters.
$Time = Join(Split(@TIME,':'),"")
;Copy the file and rename it during the copy process.
Copy $File 'X:\$StringUsername\' + $Date + '-' + $Time + '.WMA'
If @ERROR <> "0"
$Msg = MessageBox (" File copy Failed. Please try again." +
" If you continue to have trouble, please call the Helpdesk.","Error")
LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
Quit
EndIf

LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
;Sleep 1 second to get the $Time var different for each file.
Sleep 1
EndIf
Next


I was previously trying to write it like this, but I could not make it work. I don't know what the real difference is. I like the idea of deleting each file as it is copied since the way I have it now will create duplicates if one file fails to copy. Thanks
Code:

$error=@error
If $error <> 0
$Msg = MessageBox (" File copy Failed. Please try again." +
" If you continue to have trouble, please call the Helpdesk.","Error")
QUIT



dgraham
(Fresh Scripter)
2006-08-14 05:11 PM
Re: Verify succesful copy in a loop

I thought @error returns something every time. Even a successful action would return 0 wouldn't it? If I say If @error, wouldn't this exit the loop every time. Don't I have to specify If @error = "some value"?

Les
(KiX Master)
2006-08-14 05:13 PM
Re: Verify succesful copy in a loop

No, 0 would not exit.

dgraham
(Fresh Scripter)
2006-08-14 06:47 PM
Re: Verify succesful copy in a loop

Any idea why setting it as a variable wasn't working for me? Is there some reason why I can't do that?
Code:
 
$error=@error
If $error <> 0
$Msg = MessageBox (" File copy Failed. Please try again." +
" If you continue to have trouble, please call the Helpdesk.","Error")
QUIT




LonkeroAdministrator
(KiX Master Guru)
2006-08-14 07:10 PM
Re: Verify succesful copy in a loop

sure it works.

but looking at your code above, you use logaction udf after copy and you don't store the error before it.
thus, you get the error given by logaction, not the copy.


Les
(KiX Master)
2006-08-14 08:23 PM
Re: Verify succesful copy in a loop

I'm not seeing what Jooel thinks he sees.

Mart
(KiX Supporter)
2006-08-14 08:33 PM
Re: Verify succesful copy in a loop

It all depends on your setup but exiting using quit when an error occurred would completely exit kix. When you use exit it will only exit the current script and continue the parent script if there is one.

LonkeroAdministrator
(KiX Master Guru)
2006-08-14 10:23 PM
Re: Verify succesful copy in a loop

les:
Code:

;Copy the file and rename it during the copy process.
Copy $File 'X:\$StringUsername\' + $Date + '-' + $Time + '.WMA'
LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
;Sleep 1 second to get the $Time var different for each file.
Sleep 1
EndIf
Next

$Error = @ERROR



Les
(KiX Master)
2006-08-14 10:31 PM
Re: Verify succesful copy in a loop

jooel,
but further down you can see his revised code in red.


LonkeroAdministrator
(KiX Master Guru)
2006-08-14 10:44 PM
Re: Verify succesful copy in a loop

yes, and he said that code worked.
and I explained the key reason why his first code didn't.
he set the variable in wrong place.


dgraham
(Fresh Scripter)
2006-08-15 01:38 AM
Re: Verify succesful copy in a loop

Actually, I was setting the variable in both places. I tried it like this and it ignored my variable altogether. i don't get a messagebox no matter what happens, and the script continues on its merry way and deletes all my files. I WANT it to Quit so it doesn't process the last line where it deletes all the files on the thumbdrive. I think Richard H. hit on what needs doing. I need to delete each file as the copy is succesful. That way I don't delete files that didn't copy succesfully, and I don't end up with duplicates when one file fails and none of them are deleted.
Code:
 
For Each $File in $Files
If $File
;Split the time at the : character and then join the parts with no separation characters.
$Time = Join(Split(@TIME,':'),"")
;Copy the file and rename it during the copy process.
Copy $File 'X:\$StringUsername\' + $Date + '-' + $Time + '.WMA'
$Error = @error
If $Error <> 0
$MSG = Messagebox ("This" + $error + "went wrong","Error")
LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
Quit
EndIF
LogAction ("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
;Sleep 1 second to get the $Time var different for each file.
Sleep 1
EndIf
Next




I moved the $error = @error down below the loop because I couldn't get it to work inside the loop. The problem was that now I was only getting the result of the LAST file copied, and that meant I could loose data if the first file failed and the last succeded. As soon as I changed it from

$error = @error
If $Error <> 0

to

If @error <> 0

It works...
Of course, I'm pretty new, so it could be I just had something screwed up... Thanks for your help. I think I can take it from here.


NTDOCAdministrator
(KiX Master)
2006-08-15 02:11 AM
Re: Verify succesful copy in a loop

Quote:

That way I don't delete files that didn't copy succesfully, and I don't end up with duplicates when one file fails and none of them are deleted




Just curious why you didn't go with ROBOCOPY which has a switch for this and has a time switch and many, many other switches that can handle just about any type of copy method you envision.


LonkeroAdministrator
(KiX Master Guru)
2006-08-15 07:17 AM
Re: Verify succesful copy in a loop

may I ask what version of kixtart you are using?

Richard H.Administrator
(KiX Supporter)
2006-08-15 09:03 AM
Re: Verify succesful copy in a loop

I think that this is what you are after:
Code:
$sErrorMessage=""
For Each $File in $Files
If $File
;Split the time at the : character and then join the parts with no separation characters.
$Time = Join(Split(@TIME,':'),"")
;Copy the file and rename it during the copy process.
Copy $File 'X:\$StringUsername\' + $Date + '-' + $Time + '.WMA'
If @ERROR
$ERROR=@ERROR $SERROR=@SERROR
LogAction("File " + $File + " copy failed. Reason: ["+$ERROR+"] "+$SERROR)
$sErrorMessage=$sErrorMessage+"File: '"+$File+"' could not be copied .Reason: ["+$ERROR+"] "+$SERROR+@CRLF
Else
LogAction("File " + $File + " was renamed to: " + $Date + '-' + $Time + '.WMA')
; *** Uncomment the next line to remove the copied file from the thumb drive ***
;Del $File
If @ERROR
LogAction("File " + $File + " could not be deleted from source. Reason: ["+$ERROR+"] "+$SERROR)
$sErrorMessage=$sErrorMessage+"File: '"+$File+"' could not be deleted from source. Reason: ["+$ERROR+"] "+$SERROR+@CRLF
Else
LogAction("File " + $File + " deleted from source successfully.")
EndIf
EndIf
;Sleep 1 second to get the $Time var different for each file.
Sleep 1
EndIf
Next

If $sErrorMessage
$vDiscard=Messagebox("The following files errors occurred during copy:"+@CRLF+@CRFL+$sErrorMessage,"Error during copy")
EndIf



As each file is copied it is deleted if the copy was successful. If the copy fails (or the delete) the process will continue, leaving the failed copy on the source drive.

At the end you will get a pop-up showing failed copies or deletes.

You might want to add some code to delete the copied file if the delete from the source fails, but I would take the safer path and leave it there.

I've commented out the file delete until you are certain that it is all working.

BTW, the code is completely untested, so apologies for any typos.


dgraham
(Fresh Scripter)
2006-08-15 05:29 PM
Re: Verify succesful copy in a loop

I am using Kix32.exe 4.51.0.0

dgraham
(Fresh Scripter)
2006-08-15 05:51 PM
Re: Verify succesful copy in a loop

I hadn't thought of that. I might look into that, but can I use For Each kind of logic with Robocopy, or would i need to shell out inside of the loop for each file? That seems kind of awkward. Once again, I am a newbie, and I might be missing something obvious here.

dgraham
(Fresh Scripter)
2006-08-15 05:56 PM
Re: Verify succesful copy in a loop

Thanks Richard. I will play with that. Some of the stuff your doing here is a little over my head, but if I stare at it for an hour I'm sure I will figure it out. I appreciate your help.

LonkeroAdministrator
(KiX Master Guru)
2006-08-15 06:27 PM
Re: Verify succesful copy in a loop

you can replace the whole script with single shell line to robocopy.

NTDOCAdministrator
(KiX Master)
2006-08-15 10:01 PM
Re: Verify succesful copy in a loop

Here is just a brief view of what ROBOCOPY can do. The document that comes with it goes into more details and options.

Quote:


-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows :: Version XP010
-------------------------------------------------------------------------------

Started : Tue Aug 15 13:01:05 2006

Usage :: ROBOCOPY source destination [file [file]...] [options]

source :: Source Directory (drive:\path or \\server\share\path).
destination :: Destination Dir (drive:\path or \\server\share\path).
file :: File(s) to copy (names/wildcards: default is "*.*").

::
:: Copy options :
::
/S :: copy Subdirectories, but not empty ones.
/E :: copy subdirectories, including Empty ones.
/LEV:n :: only copy the top n LEVels of the source directory tree.

/Z :: copy files in restartable mode.
/B :: copy files in Backup mode.
/ZB :: use restartable mode; if access denied use Backup mode.

/COPY:copyflag[s] :: what to COPY (default is /COPY:DAT).
(copyflags : D=Data, A=Attributes, T=Timestamps).
(S=Security=NTFS ACLs, O=Owner info, U=aUditing info).

/SEC :: copy files with SECurity (equivalent to /COPY:DATS).
/COPYALL :: COPY ALL file info (equivalent to /COPY:DATSOU).
/NOCOPY :: COPY NO file info (useful with /PURGE).

/PURGE :: delete dest files/dirs that no longer exist in source.
/MIR :: MIRror a directory tree (equivalent to /E plus /PURGE).

/MOV :: MOVe files (delete from source after copying).
/MOVE :: MOVE files AND dirs (delete from source after copying).

/A+:[RASHNT] :: add the given Attributes to copied files.
/A-:[RASHNT] :: remove the given Attributes from copied files.

/CREATE :: CREATE directory tree and zero-length files only.
/FAT :: create destination files using 8.3 FAT file names only.
/FFT :: assume FAT File Times (2-second granularity).
/256 :: turn off very long path (> 256 characters) support.

/MON:n :: MONitor source; run again when more than n changes seen.
/MOT:m :: MOnitor source; run again in m minutes Time, if changed.

/RH:hhmm-hhmm :: Run Hours - times when new copies may be started.
/PF :: check run hours on a Per File (not per pass) basis.

/IPG:n :: Inter-Packet Gap (ms), to free bandwidth on slow lines.

::
:: File Selection Options :
::
/A :: copy only files with the Archive attribute set.
/M :: copy only files with the Archive attribute and reset it.
/IA:[RASHCNETO] :: Include only files with any of the given Attributes set.
/XA:[RASHCNETO] :: eXclude files with any of the given Attributes set.

/XF file [file]... :: eXclude Files matching given names/paths/wildcards.
/XD dirs [dirs]... :: eXclude Directories matching given names/paths.

/XC :: eXclude Changed files.
/XN :: eXclude Newer files.
/XO :: eXclude Older files.
/XX :: eXclude eXtra files and directories.
/XL :: eXclude Lonely files and directories.
/IS :: Include Same files.
/IT :: Include Tweaked files.

/MAX:n :: MAXimum file size - exclude files bigger than n bytes.
/MIN:n :: MINimum file size - exclude files smaller than n bytes.

/MAXAGE:n :: MAXimum file AGE - exclude files older than n days/date.
/MINAGE:n :: MINimum file AGE - exclude files newer than n days/date.
/MAXLAD:n :: MAXimum Last Access Date - exclude files unused since n.
/MINLAD:n :: MINimum Last Access Date - exclude files used since n.
(If n < 1900 then n = n days, else n = YYYYMMDD date).

/XJ :: eXclude Junction points. (normally included by default).

::
:: Retry Options :
::
/R:n :: number of Retries on failed copies: default 1 million.
/W:n :: Wait time between retries: default is 30 seconds.

/REG :: Save /R:n and /W:n in the Registry as default settings.

/TBD :: wait for sharenames To Be Defined (retry error 67).

::
:: Logging Options :
::
/L :: List only - don't copy, timestamp or delete any files.
/X :: report all eXtra files, not just those selected.
/V :: produce Verbose output, showing skipped files.
/TS :: include source file Time Stamps in the output.
/FP :: include Full Pathname of files in the output.

/NS :: No Size - don't log file sizes.
/NC :: No Class - don't log file classes.
/NFL :: No File List - don't log file names.
/NDL :: No Directory List - don't log directory names.

/NP :: No Progress - don't display % copied.
/ETA :: show Estimated Time of Arrival of copied files.

/LOG:file :: output status to LOG file (overwrite existing log).
/LOG+:file :: output status to LOG file (append to existing log).

/TEE :: output to console window, as well as the log file.

/NJH :: No Job Header.
/NJS :: No Job Summary.

::
:: Job Options :
::
/JOB:jobname :: take parameters from the named JOB file.
/SAVE:jobname :: SAVE parameters to the named job file
/QUIT :: QUIT after processing command line (to view parameters).
/NOSD :: NO Source Directory is specified.
/NODD :: NO Destination Directory is specified.
/IF :: Include the following Files.





Richard H.Administrator
(KiX Supporter)
2006-08-16 10:01 AM
Re: Verify succesful copy in a loop

Quote:

you can replace the whole script with single shell line to robocopy.




Nearly. Renaming the files is a little problematical and you'd need to rely on the ROBOCOPY log rather than the bespoke logging routine.

This appears to be a routine task intended to be carried out by end users rather than support staff, so wrapping enough code around ROBOCOPY to make the process end-user friendly enough is probably going to make the script just as complex. I guess you could pop up a window which says "some sort of error occurred please review the ROBOCOPY log", but where is the fun in that?