// // This JavaScript program copies an entire directory with // all of its files and sub-directories to a new location. // Files that already exist in the new location and have the // same size and automatically skipped. If they have a // smaller size, they will be overwritten with the // larger file. // // Written by Zsolt N. Perry in April 2023, Pensacola, Fla. // For questions, comments, feature requests, or // bug reports, write to zsnp@juno.com. // // This JavaScript program is freeware. If you want // to incorporate it or parts of it into your program, // just copy and paste whatever you need! There is no // need to ask for permission. This software is // distributed "AS IS." There is no warranty of any kind. // The author will not be held liable for any loss // resulting from the use or misuse of this software. // ////////////////////////////////////////////////// FROM = "C:\\HOME\\DOCUMENTS"; // Copy all files from this directory TO = "D:\\HOME\\DOCUMENTS"; // to this directory OUTPUT_FILE = "C:\\TEMP\\COULDNT_COPY_THESE.TXT"; // Make sure this directory exists for the output file. // Check this file for a list of files that couldn't be copied at the end. try { WshShell = new ActiveXObject("WScript.Shell"); FSO = new ActiveXObject('Scripting.FileSystemObject'); } catch(e) { EXIT("Cannot access File System."); } COPYCOUNT = 0; CANNOT_COPY = []; OpenStatusWindow(); ClearStatus(); PostStatus("Preparing to copy..."); CopyDIR(FROM); CreateFile(OUTPUT_FILE, CANNOT_COPY.join("\r\n"), 1); ALERT("DONE.\n\n" + Commify(COPYCOUNT) + " files were copied."); CloseStatusWindow(); EXIT(); ////////////////////////////////////////////////// // File | v2023.4.29 // This function reads the contents of an entire // directory with all its sub-directories and // copies each file that does not exist // yet in the destination. // // Usage: ARRAY = CopyDIR(PATH) // function CopyDIR(PATH) { var Z, F, FC, File, FullName, NEWNAME, NEWFILE, NAMEONLY; // Build target filename: PATH += ""; NEWNAME = TO + "\\" + PATH.slice(FROM.length); NEWNAME = NEWNAME.replace(/\\\\/g, "\\"); // Replace double backslash NEWNAME = NEWNAME.replace(/[\\ ]+$/, ""); // Remove last backslash CreateDirectory(NEWNAME); try { F = FSO.GetFolder(PATH); } catch (e) { return []; } for (FC = new Enumerator(F.files); !FC.atEnd(); FC.moveNext()) { FullName = FC.item() + ""; // Read files... NEWFILE = TO + "\\" + FullName.slice(FROM.length); NEWFILE = NEWFILE.replace(/\\\\/g, "\\"); // Replace double backslash NEWFILE = NEWFILE.replace(/[\\ ]+$/, ""); // Remove last backslash if (FileSize(FullName) != FileSize(NEWFILE)) // Copy if the two files are not the same { NAMEONLY = cut(FullName, "\\", 0x10101); if (IsValidFileName(NAMEONLY) == 1) CopyFile(FullName, NEWFILE); else CANNOT_COPY.push(FullName + " >|> " + NEWFILE); } ClearStatus(); PostStatus("Reading directory..."); } // Look into sub-directories... for (FC = new Enumerator(F.SubFolders); !FC.atEnd(); FC.moveNext()) CopyDIR(FC.item()); } ////////////////////////////////////////////////// // File | v2023.5.3 // This function returns 1 if the file name given // is made up of valid characters. It will return // 2 if the file name contains characters between // 127 and 255. This is still valid, but it's using // the extended ASCII character set. The function // will return 4 if the file name contains any // Unicode characters. These values can add up, so it // is possible the function will return 7, which would // indicate that the file name is valid and it contains // both Unicode characters and extended characters. // // If the file name is empty or if the file name is // longer than 256 characters or if the file name contains // ? * < > | then this function will return zero. // // NOTE: When calling this function, make sure that you are // providing the FILE NAME ONLY without the path! // If you include the path, the return value might be incorrect. // For example, if the path and the file name together are // longer than 256 bytes, the function will say that // it's an invalid file name! // // Usage: INTEGER = IsValidFileName(FILENAME) // function IsValidFileName(FILENAME) { FILENAME += ""; var RESULT = 1; var i, c, L = FILENAME.length; // Total length of file name cannot be zero or longer than 256 bytes. if (L == 0 || L > 256) return 0; for (i = 0; i < L; i++) { c = FILENAME.charCodeAt(i); if (c == 9) continue; // TAB is okay. if (c > 255) RESULT |= 4; // Check for Unicode characters. else if (c > 126) RESULT |= 2; // Check for extended ASCII characters. else if (c < 32 || c == 42 || c == 60 || c == 62 || c == 63 || c == 124) return 0; // Check for illegal characters. } // Make sure the file is made up of something // other than just a bunch of periods. return (/[^\.]/.test(FILENAME)) ? RESULT : 0; } ////////////////////////////////////////////////// // File | v2023.4.29 // This function copies a file in binary mode. // Returns 1 on success or zero if an error occurred. // Usage: STATUS = CopyFile(FROM, TO) // function CopyFile(SRC, DST) { var i, FILE, FOLDER, TREE, STATUS; // Copying... ClearStatus(); PostStatus("Copying:\n" + SRC + " (" + Commify(FileSize(SRC)) + " bytes)\n\nto\n\n" + DST); //ALERT("ABOUT TO COPY: \n" + SRC + "\n\nTO:\n\n" + DST); if (DST.indexOf("\\") >= 0) { FOLDER = DST.replace(/\\[^\\]*$/, ''); // Remove whatever comes after the last backslash try { STATUS = CreateDirectory(FOLDER); if (STATUS == 0) EXIT("Could not create directory: " + FOLDER); } catch (e) { EXIT("Failed to create folder for:\n\n" + DST); } } // Copy file... try { FILE = FSO.GetFile(SRC); FILE.Copy(DST); COPYCOUNT++; return 1; } catch (e) {} return 0; } ////////////////////////////////////////////////// // File | v2023.4.29 // This function creates a single directory if it // doesn't already exist yet. Returns: // 0 = Error occurred // 1 = Directory successfully created // 2 = Directory already exists // // Usage: INTEGER = CreateDirectory(PATH) // function CreateDirectory(PATH) { if (typeof(PATH) != 'string') return 0; if (/[\|\*\?\<\>]/.test(PATH)) return 0; // Check if there are any illegal characters PATH = PATH.replace(/\//g, "\\"); // Replace all forward slash with backslash PATH = PATH.replace(/\\\\/g, "\\"); // Replace all double backslash with single PATH = PATH.replace(/^\s*\"/, ""); // Remove double quotes prefix PATH = PATH.replace(/\"\s*$/, ""); // Remove double quotes suffix PATH = PATH.replace(/[^\\]+\\$/, ""); // Remove last backslash try { // ALERT("CreateDir: Check if folder exists: " + PATH); if (FSO.FolderExists(PATH)) return 2; FSO.CreateFolder(PATH); // Double check if folder exists now return (FSO.FolderExists(PATH)) ? 1 : 0; } catch (e) {} return 0; } ////////////////////////////////////////////////// // File | v2023.4.29 // This function returns a file's size in bytes. // Returns -1 if an error occurs or if the file doesn't exist. // Usage: INTEGER = FileSize(FILENAME) // function FileSize(FILENAME) { var F, SIZE = 0; try { if (!FSO.FileExists(FILENAME)) return -1; F = FSO.GetFile(FILENAME); SIZE = F.Size; } catch (e) { return -1; } return SIZE; } ////////////////////////////////////////////////// // This function opens a small browser window // for displaying status messages. // Usage: OpenStatusWindow() // function OpenStatusWindow() { MSIE = WScript.CreateObject("InternetExplorer.Application"); MSIE.Visible = 1; MSIE.ToolBar = 0; MSIE.StatusBar = 0; MSIE.FullScreen = 0; MSIE.Navigate("about:blank"); MSIE.RegisterAsDropTarget = 0; WScript.Sleep(100); MSIE.Height = 200; MSIE.Width = 440; MSIE.Top = 5; WScript.Sleep(100); MSIE.Left = (MSIE.document.parentWindow.screen.availWidth - 440) - 5; WScript.Sleep(200); MSIE.Document.open(); MSIE.Document.write("