Need Some Advice For Copying Files

Recommended Posts

In a nutshell, I need to copy all wma's from a digital voice recorder to specific files on our server. I've tracked down this sweet unit that is recognized as a mass storage device, and it has the USB plug built-in! For those of you interested it's the Olympus WS-100, picked it up at Best Buy for $100. Since it acts like a normal USB drive I can keep the script on the unit and run it from there...might eventually autorun it if I can find a way. The units records to five seperate folders, which works well for my project as we have five categories...I don't know what I'll do when we hit six. In each folder is whatever recordings you made, called WS_100xx.wma, where xx is a number starting at 01 and going up to 99. On the server I have a share, and in that share I have five folders all with different names. Each of those folders will be mapped to different users using login scripts. The idea is to make it as easy as possible to transfer from the device to the server. The person recording onto the device isn't very computer literate, but she can follow directions. She's going to be recording several notes into each folder, so there will never be a set amount of files. In the end I would like to tell her to just plug the device in and run the compiled script. Right now this is what I have: $axFolderA=@ScriptDir&"\DSS_FLDA\"

$axFolderB=@ScriptDir&"\DSS_FLDB\"$axFolderC=@ScriptDir&"\DSS_FLDC\"

$axFolderD=@ScriptDir&"\DSS_FLDD\"$axFolderE=@ScriptDir&"\DSS_FLDE\"

$axDestRoot="\\WARCRAFT\beta\" ; Shows the filenames of all files in the current directory.$axFindA=FileFindFirstFile($axFolderA&"*.wma") ; Check if the search was successful If$axFindA=-1 Then
MsgBox(0,"FolderA","No Files Found",5)
Else
MsgBox(0,"FolderA","Files Found",5)
EndIf

While $axFindA<>-1$axFileA=FileFindNextFile($axFindA) If @error Then ExitLoop MsgBox(0,"Results",$axFileA)
FileCopy($axFolderA&$axFileA,$axDestRoot&"red\"&$axFileA,8)
WEnd

; Close the search handle
FileClose($axFindA) ; Shows the filenames of all files in the current directory.$axFindB=FileFindFirstFile($axFolderB&"*.wma") ; Check if the search was successful If$axFindB=-1 Then
MsgBox(0,"FolderB","No Files Found",5)
Else
MsgBox(0,"FolderB","Files Found",5)
EndIf

While $axFindB<>-1$axFileB=FileFindNextFile($axFindB) If @error Then ExitLoop MsgBox(0,"Results",$axFileB)
FileCopy($axFolderB&$axFileB,$axDestRoot&"green\"&$axFileB,8)
WEnd

; Close the search handle
FileClose($axFindB) ; Shows the filenames of all files in the current directory.$axFindC=FileFindFirstFile($axFolderC&"*.wma") ; Check if the search was successful If$axFindC=-1 Then
MsgBox(0,"FolderC","No Files Found",5)
Else
MsgBox(0,"FolderC","Files Found",5)
EndIf

While $axFindC<>-1$axFileC=FileFindNextFile($axFindC) If @error Then ExitLoop MsgBox(0,"Results",$axFileC)
FileCopy($axFolderC&$axFileC,$axDestRoot&"blue\"&$axFileC,8)
WEnd

; Close the search handle
FileClose($axFindC) ; Shows the filenames of all files in the current directory.$axFindD=FileFindFirstFile($axFolderD&"*.wma") ; Check if the search was successful If$axFindD=-1 Then
MsgBox(0,"FolderD","No Files Found",5)
Else
MsgBox(0,"FolderD","Files Found",5)
EndIf

While $axFindD<>-1$axFileD=FileFindNextFile($axFindD) If @error Then ExitLoop MsgBox(0,"Results",$axFileD)
FileCopy($axFolderD&$axFileD,$axDestRoot&"yellow\"&$axFileD,8)
WEnd

; Close the search handle
FileClose($axFindD) ; Shows the filenames of all files in the current directory.$axFindE=FileFindFirstFile($axFolderE&"*.wma") ; Check if the search was successful If$axFindE=-1 Then
MsgBox(0,"FolderE","No Files Found",5)
Else
MsgBox(0,"FolderE","Files Found",5)
EndIf

While $axFindE<>-1$axFileE=FileFindNextFile($axFindE) If @error Then ExitLoop MsgBox(0,"Results",$axFileE)
FileCopy($axFolderE&$axFileE,$axDestRoot&"white\"&$axFileE,8)
WEnd

; Close the search handle
FileClose($axFindE) I have several questions...the first should be obvious. I have the same steps repeating each time for each folder. Each time the variables change inside it, so I can't figure out a way to shrink that into a function or loop...any ideas or suggestions? The next question is verification. I have the MsgBox's for testing the basic syntax, but that doesn't really tell me if the file transfered correctly. I was thinking some kinda file comparison at the byte level...isn't that what MD5 is? Again, any suggestions as to a function or tool to use to help with this would be great! And the final question is dynamic renaming...each time the script runs it could have any number of files in each folder. My first thought was to rename it during the FileCopy to something based on the date, but then what happens when I have more than one in each folder? I guess I could incorporate the time as well, but this it's just too complicated for the end user. So I was thinking something like 20060602_xx, with xx starting at 01 and going up...and I don't know how to impliment that part. To be specific, how could I make the xx incriment in the FileCopy step, or is there a better way to handle that. Eventually I want to build a GUI to handle this, and allow the user to rename the files to something a little more relevant than just the date, but I'm taking baby steps still...thanx in advance! Share this post Link to post Share on other sites I have absolutely no way of testing this obviously... But in theory this does what you want. #include <Date.au3>$axFolderA=@ScriptDir&"\DSS_FLDA\"
$axFolderB=@ScriptDir&"\DSS_FLDB\"$axFolderC=@ScriptDir&"\DSS_FLDC\"
$axFolderD=@ScriptDir&"\DSS_FLDD\"$axFolderE=@ScriptDir&"\DSS_FLDE\"

$axDestRoot="\\WARCRAFT\beta\"$TodayDate = StringReplace ( _NowCalcDate, "/", "" )

$axFindA=FileFindFirstFile($axFolderA & "*.wma")
$axFindB=FileFindFirstFile($axFolderB & "*.wma")
$axFindC=FileFindFirstFile($axFolderC & "*.wma")
$axFindD=FileFindFirstFile($axFolderD & "*.wma")
$axFindE=FileFindFirstFile($axFolderE & "*.wma")

LoopDeLoop($axFindA,"FolderA","red") LoopDeLoop($axFindB,"FolderB","green")
LoopDeLoop($axFindC,"FolderC","blue") LoopDeLoop($axFindD,"FolderD","yellow")
LoopDeLoop($axFindE,"FolderE","white") Func LoopDeLoop($FileSearchVariable,$Folder,$Color)
If $FileSearchVariable=-1 Then MsgBox(0,$Folder,"No Files Found",5)
Else
MsgBox(0,$Folder,"Files Found",5)$x = 0
While $FileSearchVariable <> -1$file=FileFindNextFile($FileSearchVariable) If @error Then ExitLoop MsgBox(0,"Results",$file)
If StringLen ( $x ) = 1 Then$x = "0" & $x EndIf FileCopy($axFolderA & $file,$axDestRoot & $Color & "\" &$TodayDate & "_" & $x & ".wma",8) If FileGetSize ($axFolderA & $file ) <> FileGetSize ($axDestRoot & $Color & "\" &$TodayDate & "_" & $x & ".wma" ) Then MsgBox ( 0, "Files Don't Match",$axFolderA & $file & " is not the same size as " &$axDestRoot & $Color & "\" &$TodayDate & "_" & $x & ".wma" ) EndIf$x = $x + 1 WEnd EndIf FileClose($FileSearchVariable)
EndFunc

Edit: I left the .wma extension off of the filecopy...

Edited by exodius

Share on other sites

For the comparison, yes, MD5/SHA1 is best (because different files can often have the same size) ...

http://www.autoitscript.com/forum/index.php?showtopic=21010

And what's wrong with date-time file names?

Even the computer illiterate can understand that convention.

-mu

Share on other sites

exodius - That looks interesting...I'll play with that and see what I get

mr.underperson - Thanx for the link, that looks like what I need. As far as the time thing goes, I agree it shouldn't be a problem, but a lot of the end users are older nurses and such. So I try to minimize the learning curve for them, and even though it would sort them logically I know they would get confused.

Share on other sites

Okay, so after some time with both suggestions heres what I have:

$axFolderA=@ScriptDir&"\DSS_FLDA\"$axFolderB=@ScriptDir&"\DSS_FLDB\"
$axFolderC=@ScriptDir&"\DSS_FLDC\"$axFolderD=@ScriptDir&"\DSS_FLDD\"
$axFolderE=@ScriptDir&"\DSS_FLDE\"$axDestRoot="\\WARCRAFT\beta\"

$axDate=@YEAR&"-"&@MON&"-"&@MDAY _axTransfer($axFolderA,"red")
_axTransfer($axFolderB,"green") _axTransfer($axFolderC,"blue")
_axTransfer($axFolderD,"yellow") _axTransfer($axFolderE,"white")

Func _axTransfer($axFolder,$axColor)

;Check for files
$axFind=FileFindFirstFile($axFolder&"*.wma")

;Check if files found
If $axFind=-1 Then MsgBox(0,$axFolder,"No Files Found",5)
Else
MsgBox(0,$axFolder,"Files Found",5) EndIf ;$x is the incrimental number at the end of the filename
$x=1 While$axFind<>-1
;Find next file
$axFile=FileFindNextFile($axFind)
If @error Then ExitLoop
MsgBox(0,"Results",$axFile) ;Copy file to network share FileCopy($axFolder&$axFile,$axDestRoot&$axColor&"\"&$axDate&"_"&$x&".wma",8) ;Open MD5 Plugin$axPlugin=PluginOpen(@ScriptDir&"\md5.dll")
;Create MD5 Hashes
$axMD5Local=FileHash($axFolder&$axFile,1)$axMD5Remote=FileHash($axDestRoot&$axColor&"\"&$axDate&"_"&$x&".wma",1)

;Compare MD5 Hashes
If $axMD5Local=$axMD5Remote Then
MsgBox(0,"Status","File Verified")
;If MD5 match then move file to archive share
FileMove($axFolder&$axFile,$axDestRoot&"archive\"&$axColor&"\"&$axDate&"_"&$x&".wma",8)
Else
MsgBox(0,"Status","File Error")
EndIf

;Close MD5 Plugin
PluginClose($axPlugin) ;Increase the number by 1$x=$x+1 WEnd ; Close the search handle FileClose($axFind)

EndFunc

It's pretty much done for now...I have to tweak some things like paths and logging, but otherwise it does everything I need!

I guess I do have one question...should the MD5 hash fail it leaves the file on the device. What would be a good way to try and retransfer the failed files without having to re-run the script?

Thanx again to you two for the suggestions...both were excellent!

Share on other sites

If the copy failed, it's unlikely to work a second time. In practice, it's unlikely to fail unless something is drastically wrong to begin with, i.e. the destination can't be created, etc. In that case, a MsgBox along the lines of "please contact <insert your name>" would probably be more appropriate.

I'd also suggest removing most all of the other msgboxes, and just have one at the end, success or failure (or "no files found, did you plug in the camera?"). Currently there's two for every file copied, which would quickly get tedious. Perhaps you just put those in for debugging. Hint: ConsoleWrite()

Looking at the script, I wonder, if someone copies a bunch of files over, and they are named, say, 2006-06-04_1.wma - 2006-06-04_5.wma; if somone then copies more files over in an hour or so, won't they overwrite the previous files? Perhaps a FileExists(), or better yet, put each batch into a folder of its own, appropriately named, of course. Or alternatively, check what the last suffix was (5) and then begin at 6.

By the way, if you are using a recent version of AutoIt (always recommended) you can do "$x += 1" instead of$x = $x + 1". It's not a biggie in this particular situation, but a very good habit to get into, will save lots of time in tight loops. There's also "&=", etc. -mu Share this post Link to post Share on other sites I'm almost done with the production version...the MsgBox's are only there to help for dev. I've got all the errors going to a log file now. I've also implimented a crude for of FileExists, but I'm still having some issue with that. Basically, I can find out if the file exists, and even initiate a rename...but then if that second file name exists, or more, then I don't know what to do. Thanx again for the tips, I'll post the file version when it's done. Share this post Link to post Share on other sites For the numbering, I was thinking more along the lines of grabbing the existing files (search handle fun again), and then grabbing the highest number so far, using it as the base for the new batch, something like... #Include <Array.au3>$xv = ""
$dir = "\\path\to\files"$my_files = FileFindFirstFile($dir & "\*.wma") while 1$name = FileFindNextFile($my_files) if @error then exitloop$array = StringSplit($name, "_")$array2 = StringSplit($array[2], ".")$xv &= $array2[1] & "," wend FileClose($my_files)
$xv = StringTrimRight($xv, 1)
$x_array = StringSplit($xv, ",")
$x = _ArrayMax($x_array, 1) + 1

Now \$x begins from wherever the last batch left off.

-mu

Create an account

Register a new account