rds_correia Posted November 3, 2011 Share Posted November 3, 2011 (edited) Greetings. Short version: I'd like to know if I can create a script that runs through a lot of folders and sub-folders, checking the contents of a lot of XML files. These XML files have a "variable" that allows me to tell which camera recorded the AVI file. The purpose of running the script is to copy all the AVI files recorded from a given camera to a different folder for archiving purposes. Long version: I have this closed source application that receives video from 8 to 10 IP cameras and then creates 2 randomly named files every 5 or 10 minutes. One of the files is an AVI (*.avi) and the other is an XML (*.xml). The AVI carries the movie while the XML carries some details about the video such as date/time and which camera recorded that video. File naming can look as cryptic as 580001000057637.avi and 580001000057637.xml. It is not only the file naming that looks complex, the folder structure is also complex, at least for someone like me who doesn't know much about coding or scripting. For instance, the main folder is 580001. This folder has no files in it, just another folder. Inside 580001 there's a folder named 000. Folder 000 doesn't have any files in it too, just other folders. Inside folder 000 there are 6 folders named 00, 01, 02, 03, 04 and 05. All these don't have any files in them too. Any of these 6 folders has 100 folders names ranging from 00 to 99. These 100's of folders are the ones who actually have files in them. So, the aforementioned file named 580001000057637.avi/.xml is stored in c:\580001\000\05\76. Whenever folder c:\580001\000\05\76 has 100 files in it, it will automatically create a new folder called c:\580001\000\05\77. Now, every XML file has information regarding the actual location where the AVI was recorded. Opening with MS Wordpad, the XML structure looks like this: <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <recording> <dataformat>video</dataformat> <starttime>2011-09-09 15:11:54:000 +0100</starttime> <endtime>2011-09-09 15:14:03:000 +0100</endtime> <nostart>false</nostart> <noend>false</noend> <servicename>323</servicename> <servicenumber></servicenumber> <deliberatebreak>0</deliberatebreak> <calldirection>Incoming</calldirection> <filename>580001000050000.avi</filename> <otherinum>0</otherinum> <recordingowners> </recordingowners> <parties> <party id="1"> <pstarttime>2011-09-09 15:13:54:043 +0100</pstarttime> <pendtime>2011-09-09 15:13:54:043 +0100</pendtime> </party> <party id="2"> <pstarttime>2011-09-09 15:13:54:043 +0100</pstarttime> <pendtime>2011-09-09 15:13:54:043 +0100</pendtime> </party> </parties> <guids> </guids> </recording> The two interesting fields are: <servicename>323</servicename> and <filename>580001000050000.avi</filename> If the XML shows servicename=323 then I need to copy the file named 580001000050000.avi to a different folder. Can this be done in AutoIt? If so, can someone point me in the right direction, please? Many thanks in advance. Cheers Edited November 10, 2011 by rds_correia Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 3, 2011 Moderators Share Posted November 3, 2011 rds_correia, The RecFileListToArray UDF in my sig will collect the names of all the .xml files within your rather convoluted tree structure. You can then use FileRead to get the content of these files and then StringRegExp to extract servicename and filename - comparing servicename to the required value is trivial. You can then use FileMove to move the .avi file in filename to another location. If the .avi file in the same location as the .xml file then that is simple; if not then you might need to scan the tree structure a second time to locate all .avi files and then search the resultant array. Does that give you enugh to go on? Why not give it a try yourself - you know where we are if you run into difficulties. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 9, 2011 Author Share Posted November 9, 2011 Greetings Melba23, I've tested a RecFileListToArray and it took a lot of time browsing through all my directories/files and during that time my CPU was running at 100%. I guess I've got too many files to browse through... I would like to minimize the impact of the script in terms of CPU usage. After all, it needs to be ready to take more recordings. Important: my script's purpose is to filter recordings from the _last_couple_of_days_only. Which means that I can start ignoring 5800010000000 through 5800010000575 and start focusing only on 5800010000576 and further. But I will have to worry about 580001000 when 5800010009999 gets filled with 100 avi's. Only then the system will create a 5800010010000. And when 5800019999999 gets filled with 100 avi's then the system will create 5800020000000 and so on. So I was thinking about this logic: expandcollapse popup:start $1st_folder=580001 $2nd_folder=000 $3rd_folder=05 $4th_folder=75 :check_1st_folder if $1st_folder exists then if $1st_folder+1 exists then $1st_folder=$1st_folder+1 goto :check_1st_folder else :check_2nd_folder if $2nd_folder exists then if $2nd_folder+1 exists then $2nd_folder=$2nd_folder+1 goto :check_2nd_folder else :check_3rd_folder if $3rd_folder exists then if $3rd_folder+1 exists then $3rd_folder=$3rd_folder+1 goto :check_3rd_folder else :check_4th_folder if $4th_folder exists then if $4th_folder+1 exists then $4th_folder=$4th_folder+1 goto :check_4th_folder else START USING RECFILELISTTOARRAY USING THE LAST FOLDER FOUND BY THIS ROUTINE else display error "4th folder doesn't exist!" else display error "3rd folder doesn't exist!" else display error "2nd folder doesn't exist!" else display error "1st folder doesn't exist!" What do you think? I think this way I'd save some CPU cycles, right? Being a total script-noob, could you help me with the code? Thanks in advance. Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 9, 2011 Moderators Share Posted November 9, 2011 rds_correia, I see your problem and I am working on it. Please be patient - I think I have a good handle on how to solve the problem but it needs a lot of testing to be sure it works. Would you have a problem with saving a small file which holds details of the last file that was opened? That way we only open and examine files saved since then. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
kylomas Posted November 9, 2011 Share Posted November 9, 2011 (edited) rds_correia,Check this out http://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx.kylomasEdit: Ther are also hits within the forums, in particular this link http://www.autoitscript.com/forum/index.php?showtopic=42511&st=0Edit: Apologies, I forgot to include that this technique involves monitoring changes to a specific folder, or set of folders and if chaged, archive/copy the new/changed files. As opposed to spinning through files and programmatically moving/grouping them. Edited November 9, 2011 by kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 9, 2011 Moderators Share Posted November 9, 2011 rds_correia,Have a try with this script and see how you get on. First create a small file in the same folder as the script which looks like this:580001 000 05 76 37This is based on the example data you gave me - just adjust the values to match a suitable point in the tree structure. The final value is the index number of the final file you assume had been examined on teh last run - 580001000057637.xml. The elements of this file determine the last file that was examined - the following script should examine all subsequent files created in the tree even if new folders have been created. Note we are only looking at the files in one folder at a time using _FileListToArray - this should speed things up a a lot: expandcollapse popup#include <File.au3> #include <Array.au3> Global $aLast_Path ; Name of the file we save to hold the data of the last file examined $sLast_Read = "Last Read.txt" ; Read the file into an array _FileReadToArray(@ScriptDir & "" & $sLast_Read, $aLast_Path) ; Here we see the eleemnts of the last file examined on the last run _ArrayDisplay($aLast_Path, "Current") ; As long as the last file examined did not end in 99 we need to examine the same folder for new files If $aLast_Path[5] <> "99" Then ; So pass the path and file details to the function $iLast_File = List_Files($aLast_Path, $aLast_Path[5]) ; And save the new file data $aLast_Path[5] = $iLast_File EndIf ; If the final file ends in less than 99 there is still space in this folder so no point in looking further ; But if it does end in 99 we need to look further If $aLast_Path[5] = "99" Then ; Create a new array to hold the path data $aNew_Path = $aLast_Path ; And now we look for any new folders in the series until we find one that does not exist While 1 ; Add 1 to the folder and reset to 00 if needed $aNew_Path[4] = StringFormat("%02i", Mod($aNew_Path[4] + 1, 100)) ; If we did reset to 00 then we need to check the level above If $aNew_Path[4] = "00" Then ; Again we add 1 and reset to 00 if required $aNew_Path[3] = StringFormat("%02i", Mod($aNew_Path[3] + 1, 100)) ; And if we reset to 00 we need to check the level above If $aNew_Path[3] = "00" Then ; Add 1 but this time we reset to 000 if required $aNew_Path[2] = StringFormat("%03i", Mod($aNew_Path[2] + 1, 1000)) ; And again we move up a level if the lower folder was reset If $aNew_Path[2] = "000" Then ; If this one gets to 589999 then you need to restart - or add another level to this tree! $aNew_Path[1] = $aNew_Path[1] + 1 EndIf EndIf EndIf ; Now see if this path exists $sNew_Path = "C:" & _ArrayToString($aNew_Path, "", 1, 4) & "" If FileExists($sNew_Path) Then ; If it does we save it to write to disk as the new start point ;ConsoleWrite("Looking at " & $sNew_Path & @CRLF) $aLast_Path = $aNew_Path ; We pass the path to the function - note no file data passed as we are going to start at 00 $iLast_File = List_Files($aNew_Path) ; And save the numbe rof the last file examined $aLast_Path[5] = $iLast_File Else ; If the path does not exist then we exit the loop ExitLoop EndIf WEnd EndIf ; Here we see the elements of the final file that was examined _ArrayDisplay($aLast_Path) ; This can be saved to disk to act as the start point for the next search ; This is the function that searches within the files - note the start is at 00 if no parameter passed Func List_Files($aPath, $sStart = "00") ; Create the path and filename from the passed parameters $sPath = "C:" & _ArrayToString($aPath, "", 1, 4) & "" $sFile = $sPath & _ArrayToString($aPath, "", 1, 4) & $sStart & ".xml" ; Get a list of all the files matching our search in the folder $aFile_List = _FileListToArray($sPath & "", "*.xml", 1) ;_ArrayDisplay($aFile_List, $sStart) ; Now we see if we start at 00 or further in If $sStart = "00" Then ; If we start at 00 we examine all the files found For $j = 1 To $aFile_List[0] ; Pass the filename to the function Examine_File($sPath & $aFile_List[$j]) $sFile_Treated = $aFile_List[$j] Next Else ; If we have already examined some of the files in this folder we find how far we have already been For $i = 1 To $aFile_List[0] If $sPath & $aFile_List[$i] = $sFile Then ExitLoop EndIf Next ; And then examine the files from then on For $j = $i + 1 To $aFile_List[0] ; Pass the filename to the function Examine_File($sPath & $aFile_List[$j]) $sFile_Treated = $aFile_List[$j] Next EndIf ; Finally we extract and return the last 2 digits of the filename so we know how far we have read in this folder Return StringRegExpReplace($sFile_Treated, ".*(d{2}).xml", "$1") EndFunc Func Examine_File($sFile) ; Read the content of the file $sFile_Content = FileRead($sFile) ; Extract the data we require $aData = StringRegExp($sFile_Content, "(?i)(?U)name>(.*)<", 3) ; And display it MsgBox(0, "Data", "Extracting from file: " & $sFile & @CRLF & @CRLF & _ @TAB & "Servicename: " & @TAB & $aData[0] & @CRLF & _ @TAB & "Filename: " & @TAB & $aData[1]) EndFuncSRE explanation:(?i) - Case insensitive (you never know!) (?U) - Shortest match name> - Look for this text (.*) - Capture all text afterwards < - Until we find this 3 - Get an array of all matchesAt the moment we make no changes to the small file which details the last file examined - we can do that when we know the script works. Similarly we do nothing with the data we extract from the file - other than display it to see if it is what we want. Give this a try and see if it extracts the data correctly from the files following the one set in the small data file. If it does we can look to refining it to do exactly what you want. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 Hi Melba23,Thank you very much for your help.I have tried your script on my server.First it displays a window named "Current" which shows a list of the items that I have copied to the "Last Read.txt" file.And then it crashes with an error message saying:Line 96 (File "c:\script\test.au3"): For $i=1 To $aFile_List[0] For $i=1 To $aFile_List^ Error Error: subscript used with non-Array variablePlus, yesterday I was thinking about the script and I noticed that I forgot to mention one thing important: in the future, when I run the script I want to see all the video recordings from the previous day.But, the previous day video recordings can be archived across two or more folders...They could be 580001\000\05\73\580001000057381.avi till 580001\000\05\75\580001000057523.aviWhich means that, when I run my script, I immediately want to find the last folder.Then I want to check if that folder has recordings from the previous day.If so, then I want to mark that folder for further usage.Then I want to check if the previous folder has recordings from the previous day.If so, then I want to mark that folder for further usage, and so on.When I hit a folder that doesn't have recordings from the previous day, then I stop looking for more previous folders.Then I take the folders previously marked for further usage and I check all the XML files on them.I want to mark all the files with XML references from the previous day and with XML references of the camera that I want to inspect.This can be done checking the <starttime></starttime> and the <servicename></servicename> fields in the XML files.Now that I have the recordings from that particular day and from that particular camera, now I can copy the corresponding AVI files to a separate directory.Thanks a lot for all the help your giving me.Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 rds_correia,That error means you have no files in a folder - which according to what you told me earlier should never happen. And I see you are changing the goalposts in mid-match. Ah well - let us see what we can do now. However, we shall proceed in small steps. Based on your new request, try running this script and see if it works for you as well it works for me when I test it. It should work its way through the tree starting at "C:5800010000000" and find the last created folder in the sequence you described - these folders are then displayed in a dialog. Please check to see if the list is complete and the final folder displayed is indeed the final one in your tree. The script then lists the .xml files within these folders - starting with the last created and working backwards. You will see either a dialog displaying the files or a MsgBox telling you there are no files is that folder. You can easily stop the script at this point so you do not have to wait for all the folder to be listed! expandcollapse popup#include <Array.au3> #include <File.au3> Global $aPath[5] = [4, "580001", "000", "00", "00"] ; Find last folder $aFolder_List = _Last_Folder($aPath) _ArrayDisplay($aFolder_List) ; Work backwards through the folder list For $i = $aFolder_List[0] To 1 Step -1 ; Read the list of files in this folder $aFile_List = _FileListToArray($aFolder_List[$i] & "", "*.xml", 1) If IsArray($aFile_List) Then _ArrayDisplay($aFile_List, $aFolder_List[$i]) Else MsgBox(0, "Error", "No files found in" & @CRLF & $aFolder_List[$i]) Exit EndIf Next Func _Last_Folder($aPath) ; Create an array to hold the list of folders found Local $aFolders[100] = [1, "C:" & _ArrayToString($aPath, "", 1, 4) & ""] While 1 ; Add 1 to the folder and reset to 00 if needed $aPath[4] = StringFormat("%02i", Mod($aPath[4] + 1, 100)) ; If we did reset to 00 then we need to check the level above If $aPath[4] = "00" Then ; Again we add 1 and reset to 00 if required $aPath[3] = StringFormat("%02i", Mod($aPath[3] + 1, 100)) ; And if we reset to 00 we need to check the level above If $aPath[3] = "00" Then ; Add 1 but this time we reset to 000 if required $aPath[2] = StringFormat("%03i", Mod($aPath[2] + 1, 1000)) ; And again we move up a level if the lower folder was reset If $aPath[2] = "000" Then ; If this one gets to 589999 then you need to restart - or add another level to this tree! $aPath[1] = $aPath[1] + 1 EndIf EndIf EndIf ; Now see if this path exists $sNext_Path = "N:" & _ArrayToString($aPath, "", 1, 4) & "" If Not FileExists($sNext_Path) Then ; If the path does not exist then we return the list of folders found ReDim $aFolders[$aFolders[0] + 1] Return $aFolders Else ; The folder exists so add it to the array - resizing if necessary $aFolders[0] += 1 If UBound($aFolders) <= $aFolders[0] Then ReDim $aFolders[$aFolders[0] * 2] EndIf $aFolders[$aFolders[0]] = $sNext_Path EndIf WEnd EndFuncI hope you do not see the MsgBox as that would mean that I have misunderstood everything you have told me about the way the folder structure is created. Let me know how it works. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 Hi Melba23,Once again, thanks a lot for your help.I have tested your last script and I got a MsgBox.But I have possibly found the issue.I failed to tell you the FULL path where my cameras are recording.It is not c:5800010000000580001000000000(..99).avi.Instead it it c:surveillance5800010000580001000000000(..99).avi.Maybe your scripts are assuming a full path, right?My bad, I'm awfully sorry.Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 rds_correia, I failed to tell you the FULL path where my cameras are recording Try this version: expandcollapse popup#include <Array.au3> #include <File.au3> Global $aPath[5] = [4, "580001", "000", "00", "00"] ; Find last folder $aFolder_List = _Last_Folder($aPath) _ArrayDisplay($aFolder_List) ; Work backwards through the folder list For $i = $aFolder_List[0] To 1 Step -1 ; Read the list of files in this folder $aFile_List = _FileListToArray($aFolder_List[$i] & "\", "*.xml", 1) If IsArray($aFile_List) Then _ArrayDisplay($aFile_List, $aFolder_List[$i]) Else MsgBox(0, "Error", "No files found in" & @CRLF & $aFolder_List[$i]) Exit EndIf Next Func _Last_Folder($aPath) ; Create an array to hold the list of folders found Local $aFolders[100] = [1, "C:\surveillance\" & _ArrayToString($aPath, "\", 1, 4) & "\"] While 1 ; Add 1 to the folder and reset to 00 if needed $aPath[4] = StringFormat("%02i", Mod($aPath[4] + 1, 100)) ; If we did reset to 00 then we need to check the level above If $aPath[4] = "00" Then ; Again we add 1 and reset to 00 if required $aPath[3] = StringFormat("%02i", Mod($aPath[3] + 1, 100)) ; And if we reset to 00 we need to check the level above If $aPath[3] = "00" Then ; Add 1 but this time we reset to 000 if required $aPath[2] = StringFormat("%03i", Mod($aPath[2] + 1, 1000)) ; And again we move up a level if the lower folder was reset If $aPath[2] = "000" Then ; If this one gets to 589999 then you need to restart - or add another level to this tree! $aPath[1] = $aPath[1] + 1 EndIf EndIf EndIf ; Now see if this path exists $sNext_Path = "C:\surveillance\" & _ArrayToString($aPath, "\", 1, 4) & "\" If Not FileExists($sNext_Path) Then ; If the path does not exist then we return the list of folders found ReDim $aFolders[$aFolders[0] + 1] Return $aFolders Else ; The folder exists so add it to the array - resizing if necessary $aFolders[0] += 1 If UBound($aFolders) <= $aFolders[0] Then ReDim $aFolders[$aFolders[0] * 2] EndIf $aFolders[$aFolders[0]] = $sNext_Path EndIf WEnd EndFunc Does it work now? M23 rds_correia 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 Does it work now? Worked like a charm Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 rds_correia,Good! And now the next step. Now we read the camera and date values from within the .xml files to see if we need to deal with the associated .avi file. Try running this script - you should see the camera and YYYY-MM-DD date for each file appear in the MsgBox:expandcollapse popup#include <Array.au3> #include <File.au3> Global $aPath[5] = [4, "580001", "000", "00", "00"] ; Find last folder $aFolder_List = _Last_Folder($aPath) ;_ArrayDisplay($aFolder_List) ; Work backwards through the folder list For $i = $aFolder_List[0] To 1 Step -1 ; Read the list of files in this folder $aFile_List = _FileListToArray($aFolder_List[$i] & "", "*.xml", 1) _ArrayDisplay($aFile_List, $aFolder_List[$i]) If IsArray($aFile_List) Then _Check_Files($aFile_List, $aFolder_List[$i] & "") Else MsgBox(0, "Error", "No files found in" & @CRLF & $aFolder_List[$i]) Exit EndIf Next Func _Check_Files($aArray, $sPath) For $i = $aArray[0] To 1 Step -1 ; Read the content of the file $sFile_Content = FileRead($sPath & $aArray[$i]) ; Extract the data we require ; Is it the correct camera $aCamera = StringRegExp($sFile_Content, "(?i)(?U)servicename>(.*)<", 3) ; And date $aDate = StringRegExp($sFile_Content, "(?i)(?U)starttime>(.*)x20", 3) ; And display it MsgBox(0, "Data", "Extracting from file: " & $aArray[$i] & @CRLF & @CRLF & _ @TAB & "Camera: " & @TAB & $aCamera[0] & @CRLF & _ @TAB & "Date : " & @TAB & $aDate[0]) Next EndFunc Func _Last_Folder($aPath) ; Create an array to hold the list of folders found Local $aFolders[100] = [1, "C:surveillance" & _ArrayToString($aPath, "", 1, 4) & ""] While 1 ; Add 1 to the folder and reset to 00 if needed $aPath[4] = StringFormat("%02i", Mod($aPath[4] + 1, 100)) ; If we did reset to 00 then we need to check the level above If $aPath[4] = "00" Then ; Again we add 1 and reset to 00 if required $aPath[3] = StringFormat("%02i", Mod($aPath[3] + 1, 100)) ; And if we reset to 00 we need to check the level above If $aPath[3] = "00" Then ; Add 1 but this time we reset to 000 if required $aPath[2] = StringFormat("%03i", Mod($aPath[2] + 1, 1000)) ; And again we move up a level if the lower folder was reset If $aPath[2] = "000" Then ; If this one gets to 589999 then you need to restart - or add another level to this tree! $aPath[1] = $aPath[1] + 1 EndIf EndIf EndIf ; Now see if this path exists $sNext_Path = "C:surveillance" & _ArrayToString($aPath, "", 1, 4) & "" If Not FileExists($sNext_Path) Then ; If the path does not exist then we return the list of folders found ReDim $aFolders[$aFolders[0] + 1] Return $aFolders Else ; The folder exists so add it to the array - resizing if necessary $aFolders[0] += 1 If UBound($aFolders) <= $aFolders[0] Then ReDim $aFolders[$aFolders[0] * 2] EndIf $aFolders[$aFolders[0]] = $sNext_Path EndIf WEnd EndFuncIf this works we can run a couple of tests against these values to confirm that they are yesterday's files from the correct camera and then extract the .avi name for further treatment. I presume you are intending to create a GUI to wrap all this later on and that will include some way of defining the camera ID. I will hard code it for the moment - the date is trivial to obtain. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 the date is trivial to obtain. You're not thinking of reading the xml timestamp, are you?Because the files timestamps and the actual recording date/time can actually differ by several hours.The avi and the xml both come from remote servers that send these files to a centralized server that stores them using this cryptic file/folder scheme.If a link between a remote server and the the centralized server goes offline, then xml+avi timestamps will be all wrong.Let me try your last script and I'll report back in a couple of minutes.Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 (edited) rds_correia,You're not thinking of reading the xml timestamp, are you?I was going to use the<STARTTIME>2011-09-09 15:11:54:000 +0100</STARTTIME>data from the file. If that is not the correct date, then which bit of the file data does hold the correct data? M23Edit: I am assuming that omnce I hit the first file with the day before yesterday's date we can abandon the search. Is that a valid assumption in your rather wacky world of files? Edited November 10, 2011 by Melba23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 I was going to use the<STARTTIME>2011-09-09 15:11:54:000 +0100</STARTTIME>data from the file. If that is not the correct date, then which bit of the file data does hold the correct data? That's perfect.That's the only place where we can be sure about the video recording date/time.On my last post I was talking about the avi/xml timestamp (the one you can see in Windows File Explorer) .Edit: I am assuming that omnce I hit the first file with the day before yesterday's date we can abandon the search. Is that a valid assumption in your rather wacky world of files? Well...you've brought up an interesting question...I'm not sure.I would guess that a day can be broken in two just because of the link-down issue that I just told you right above.But for now, let's just ignore that possibility.If that actually happens, it will only be a couple of times and it will be ok to search/copy the files manually instead of using the script .I'm curious about your last script.Apparently it ran fine.I'm just wondering what you mean by "extracting file ...".Was it really copying stuff? If so, where to?Other than that, it seemed like it did exactly what we were hoping for.Thanks a bunch.Cheers Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 I presume you are intending to create a GUI to wrap all this later on and that will include some way of defining the camera ID. I will hard code it for the moment - the date is trivial to obtain. In fact I intend to write a small GUI to wrap it up.Maybe with Koda? What do you advise?A real bonus would be being able to choose multiple cameras at once.A range like 320..329.But I wasn't born to code so it will take time, lot's of time .Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 rds_correia, Looks like we might be in business! Here is the next stage - extracting the .avi name ready for you copy it elsewhere: expandcollapse popup#include <Array.au3> #include <File.au3> #include <Date.au3> Global $aPath[5] = [4, "580001", "000", "00", "00"] Global $sCamera_ID = "323" Global $sYesterday = StringReplace(_DateAdd("D", -1, @YEAR & "/" & @MON & "/" & @MDAY), "/", "-") Global $sBefore_Yesterday = StringReplace(_DateAdd("D", -2, @YEAR & "/" & @MON & "/" & @MDAY), "/", "-") ; Find last folder $aFolder_List = _Last_Folder($aPath) ; Work backwards through the folder list For $i = $aFolder_List[0] To 1 Step -1 ; Read the list of files in this folder $aFile_List = _FileListToArray($aFolder_List[$i] & "", "*.xml", 1) ;_ArrayDisplay($aFile_List, $aFolder_List[$i]) If IsArray($aFile_List) Then If _Check_Files($aFile_List, $aFolder_List[$i]) Then ; We have reached the files from 2 days ago ExitLoop EndIf Else ; There are no files to check - this should never happen ExitLoop EndIf Next MsgBox(0, "Done", "All files from " & $sYesterday & @CRLF & "taken by camera " & $sCamera_ID & @CRLF & "have been dealt with") Func _Check_Files($aArray, $sPath) ; Clear the "day before yesterday" flag $fEnded = False For $i = $aArray[0] To 1 Step -1 ; Read the content of the file $sFile_Content = FileRead($sPath & $aArray[$i]) ; Is it the correct date $aDate = StringRegExp($sFile_Content, "(?i)(?U)starttime>(.*)x20", 3) Switch $aDate[0] Case $sYesterday ; Is it the correct camera $aCamera = StringRegExp($sFile_Content, "(?i)(?U)servicename>(.*)<", 3) If $aCamera[0] = $sCamera_ID Then ; Extract the .avi name $aAVI = StringRegExp($sFile_Content, "(?i)(?U)filename>(.*)<", 3) ; And display the data ConsoleWrite("File: " & $sPath & $aArray[$i] & @CRLF) ConsoleWrite(@TAB & "Avi: " & $sPath & $aAVI[0] & @CRLF & @TAB & " could now be copied" & @CRLF) EndIf Case $sBefore_Yesterday ; Set the flag $fEnded = True ; No point in going back further ExitLoop EndSwitch Next Return $fEnded EndFunc Func _Last_Folder($aPath) ; Create an array to hold the list of folders found Local $aFolders[100] = [1, "C:surveillance" & _ArrayToString($aPath, "", 1, 4) & ""] While 1 ; Add 1 to the folder and reset to 00 if needed $aPath[4] = StringFormat("%02i", Mod($aPath[4] + 1, 100)) ; If we did reset to 00 then we need to check the level above If $aPath[4] = "00" Then ; Again we add 1 and reset to 00 if required $aPath[3] = StringFormat("%02i", Mod($aPath[3] + 1, 100)) ; And if we reset to 00 we need to check the level above If $aPath[3] = "00" Then ; Add 1 but this time we reset to 000 if required $aPath[2] = StringFormat("%03i", Mod($aPath[2] + 1, 1000)) ; And again we move up a level if the lower folder was reset If $aPath[2] = "000" Then ; If this one gets to 589999 then you need to restart - or add another level to this tree! $aPath[1] = $aPath[1] + 1 EndIf EndIf EndIf ; Now see if this path exists $sNext_Path = "C:surveillance" & _ArrayToString($aPath, "", 1, 4) & "" If Not FileExists($sNext_Path) Then ; If the path does not exist then we return the list of folders found ReDim $aFolders[$aFolders[0] + 1] Return $aFolders Else ; The folder exists so add it to the array - resizing if necessary $aFolders[0] += 1 If UBound($aFolders) <= $aFolders[0] Then ReDim $aFolders[$aFolders[0] * 2] EndIf $aFolders[$aFolders[0]] = $sNext_Path EndIf WEnd EndFunc Is that what you wanted? M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 Looks like we might be in business! Wooohoooo Here is the next stage - extracting the .avi name ready for you copy it elsewhere: ...Is that what you wanted? What? Having a list of avi files that I can later copy to a folder? Sure! That's exactly what I'm looking for.Let me try your last script and I'll report back.Cheers Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 10, 2011 Moderators Share Posted November 10, 2011 rds_correia,Having a list of avi files that I can later copy to a folder?I think it would be more elegant to copy them as you find them - why make a list and then rerun it? As to the GUI - please do try and code something yourself. But you know where we are if you run into trouble. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
rds_correia Posted November 10, 2011 Author Share Posted November 10, 2011 I just tried your last script and I get something like "all files have been dealt with" but I don't see any "avi: c:surveillance89000100005848900010000584**.avi could now be copied". I guess I'm missing something... Cheers Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now