
Synchronize or merge two folders

tony
I haven't tested this extensively, caveat emptor!
Files in destination folder are overwritten by newer versions in source folder.
This could potentially be used for client-based synchronization of procedure files over a network.
// this is not a complete synchronization, files are not deleted from the // destination folder if they don't exist in the source folder. So more // of a sync-merge. function SyncTest(int bothways) NewPath/Q/O/M="Select Source Folder" pathSource PathInfo pathSource string source = s_path NewPath/Q/O/M="Select Destination Folder" pathDestination PathInfo pathDestination string destination = s_path string strOverwrites = SyncFolder(source, destination, test=1, bothways=bothways) // check that we don't somehow what to move a file in both directions if (CheckForError(source, destination, strOverwrites)) doAlert 0, "Unexpected sync error, quitting without copying anything" return 0 endif int numOverwrites = ItemsInList(strOverwrites) if (numOverwrites) DoAlert 1, num2str(numOverwrites) + " files will be overwritten.\r\rContinue?" if (v_flag==2) return 0 endif endif SyncFolder(source, destination, bothways=bothways) end // Merges folders like copyFolder on Windows // Files in destination folder are overwritten by more recently modified // files from source // Setting test=1 doesn't copy anything but generates a list of files // that would be overwritten // ignore is a string list of names of files that should not be copied. // set bothways=1 for bidirectional synchonization // Recommended to run with test=1 to check for problems before trying to sync! function/S SyncFolder(source, destination, [backupPathStr, test, ignore, bothways]) string source, destination int test string backupPathStr // must be no more than one sublevel below an existing folder string ignore // list of filenames that won't be copied int bothways test = ParamIsDefault(test) ? 0 : test backupPathStr = SelectString(ParamIsDefault(backupPathStr), backupPathStr, "") ignore = SelectString(ParamIsDefault(ignore), ignore, "") int backup = (strlen(backupPathStr) > 0) bothways = ParamIsDefault(bothways) ? 0 : bothways // clean up paths source = ParseFilePath(2, source, ":", 0, 0) destination = ParseFilePath(2, destination, ":", 0, 0) if (backup) backupPathStr = ParseFilePath(2, backupPathStr, ":", 0, 0) endif // check that source and destination folders exist GetFileFolderInfo/Q/Z source int sourceOK = V_isFolder GetFileFolderInfo/Q/Z destination if (sourceOK==0 || V_isFolder==0) return "" endif int folderIndex, fileIndex, subfolderIndex int folderCount = 1, sublevels = 0 string folderList, fileList, fileName string copiedFileList = "", subPathStr = "" string destFolderStr = "", sourceFolderStr = "", backupFolderStr = "" variable sourceMod int filefound Make/free/T/N=0 w_folders, w_subfolders w_folders = {source} do // step through folders at current sublevel for (folderIndex=0;folderIndex<numpnts(w_folders);folderIndex+=1) // figure out destination folder to match current source folder sourceFolderStr = w_folders[folderIndex] subPathStr = (sourceFolderStr)[strlen(source),strlen(sourceFolderStr)-1] destFolderStr = destination + subPathStr backupFolderStr = backupPathStr + subPathStr // make sure that folder exists at destination if (test == 0) NewPath/C/O/Q/Z tempPathSync, destFolderStr if (backup) NewPath/C/O/Q/Z tempPathSync, backupFolderStr endif endif // get list of source files in indexth folder at current sublevel NewPath/O/Q/Z tempPathSync, sourceFolderStr fileList = IndexedFile(tempPathSync, -1, "????") // remove files from list if they match an entry in ignorefileList fileList = RemoveFromListWC(fileList, ignore) // copy files for (fileIndex=0;fileIndex<ItemsInList(fileList);fileIndex+=1) fileName = StringFromList(fileIndex, fileList) GetFileFolderInfo/Q/Z sourceFolderStr + fileName sourceMod = V_modificationDate // store source file modification date GetFileFolderInfo/Q/Z destFolderStr + fileName filefound = (v_flag == 0) && v_isFile // allow for 10s difference in modification time in case // different file systems don't match modification times // precisely. // this may have to be rethought if problems arise. sourceMod = filefound ? V_modificationDate < (sourceMod-10) : 1 // sourceMod = 1 for file to be copied if (test) if (filefound && sourceMod) // file is to be overwritten copiedFileList = AddListItem(destFolderStr + fileName, copiedFileList) endif else if (backup) // back up any files that are to be overwritten if (filefound && sourceMod) // file is to be overwritten CopyFile/Z/O destFolderStr + fileName as backupFolderStr + fileName endif endif if (sourceMod) CopyFile/Z/O sourceFolderStr + fileName as destFolderStr + fileName copiedFileList = AddListItem(destFolderStr + fileName, copiedFileList) endif endif endfor // make a list of subfolders in current folder folderList = IndexedDir(tempPathSync, -1, 0) // add the list of folders to the subfolders wave for (subfolderIndex=0;subfolderIndex<ItemsInList(folderList);subfolderIndex+=1) w_subfolders[numpnts(w_subfolders)] = {sourceFolderStr + StringFromList(subfolderIndex, folderList) + ":"} folderCount += 1 endfor endfor // prepare for next sublevel iteration Duplicate/T/O/free w_subfolders, w_folders Redimension/N=0 w_subfolders sublevels += 1 if (numpnts(w_folders) == 0) break endif while(1) KillPath/Z tempPathSync if (bothways) copiedFileList += SyncFolder(destination, source, backupPathStr=backupPathStr, test=test, ignore=ignore, bothways=0) endif return SortList(copiedFileList) end // returns listStr, purged of any items that match an item in ZapListStr. // Wildcards okay! Case insensitive. function/S RemoveFromListWC(string listStr, string zapListStr) string removeStr = "" int i for (i=ItemsInList(zapListStr)-1;i>=0;i-=1) removeStr += ListMatch(listStr, StringFromList(i, zapListStr)) endfor return RemoveFromList(removeStr, listStr, ";", 0) end function CheckForError(string source, string destination, string strFileList) if (ItemsInList(strFileList) == 0) return 0 endif wave/T wText = ListToTextWave(strFileList, ";") wText = RemoveStart(wText, source) wText = RemoveStart(wText, destination) FindDuplicates/Z/free/DT=dupsWave wText return numpnts(dupsWave) end function/S RemoveStart(string str, string startingStr) int len = strlen(startingStr) if (len == 0) return str endif if (cmpstr(startingStr, str[0,len-1]) == 0) return str[len,Inf] endif return str end

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More