Delete to the "ForDeletion" directory for the drive#gotrash@Script JScriptDOpus.Output ("- - - - - - - ->")// Deletion (to be used in conjunction with Restoration)// (C) 2015 JulianON// V1.1 12/10/15// This is a script for Directory Opus.// See http://resource.dopus.com/viewtopic.php?f=35&t=25248 for development information. // ********** TWO INITIAL CONFIGURATION STEPS ************// 1. THE MAXIMUM NUMBER OF DELETIONS AT ONE TIME: This safety switch can be changed to any positive whole number.// Note, however, that a directory consisting of 1000 files and subdirectories counts as one item.var nMaxDeletes = 100 // *********************************************************// 2. THE DELETION DIRECTORY: // The "ForDeletion" directory needs to be set for each of the 26 possible letter-mapped drives // and for unmapped network drives. For the 26 letter-mapped drives, this is done by the array entries // aBibForDrive [0] to aBinForDrive [26], and for the unmapped network drives by aBinForDrive [0].// Two variables sGeneralBin and sDriveBin are there only to save typing below, and are not necessary — // explicit paths (with quotes) can be typed in as entries.// Use double backslashes \\ for each singe backslash \ as in the examples below. with no final backslash.// (a) To produce a "ForDeletion" directory that could be on another drive, retain the drive at the start // of the full directory path, and omit the final backslash. For example: "C:\\AA\\BB\\CC". // This may well be the best approach for mapped and unmapped network drives.// It is, of course, quite insecure for mounted encrytped drives.// (b) To produce a deletion directory on the same drive so that deletion is done within the same drive, omit the drive // and omit the initial and final backslashes. For example: "AA\\BB\\CC"// (c) Setting the entry to the empty string "" (or commenting out the entry) triggers the ordinary DOpus "Delete"// command, which may or may not send items to the normal Windows Recycle Bin, depending on the drive.sGeneralBin = "D:\\@@ForDeletion" // A single "ForDeletion" directory on a fixed drive. Edit the path, with the drive sDriveBin = "@@ForDeletion" // A "ForDeletion" directory on the particular drive. Edit the path, omitting the dirvevar aBinForDrive = new ArrayaBinForDrive [0] = sGeneralBin // This entry is for unmapped network drive deletionsaBinForDrive [1] = sGeneralBin // For Drive A: See line 30aBinForDrive [2] = sGeneralBin // For Drive B:aBinForDrive [3] = "" // For Drive C: The empty string "" here will trigger the normal Windows Delete commandaBinForDrive [4] = "" // For Drive D:aBinForDrive [5] = "" // For Drive E:aBinForDrive [6] = sGeneralBin // For Drive F:aBinForDrive [7] = sGeneralBin // For Drive G:aBinForDrive [8] = sGeneralBin // For Drive H:aBinForDrive [9] = sGeneralBin // For Drive I:aBinForDrive [10] = sGeneralBin // For Drive J:aBinForDrive [11] = sGeneralBin // For Drive K:aBinForDrive [12] = sGeneralBin // For Drive L:aBinForDrive [13] = sGeneralBin // For Drive M:aBinForDrive [14] = sDriveBin // For Drive N: See line 31aBinForDrive [15] = sDriveBin // For Drive O:aBinForDrive [16] = sDriveBin // For Drive P:aBinForDrive [17] = sDriveBin // For Drive Q:aBinForDrive [18] = sDriveBin // For Drive R:aBinForDrive [19] = sDriveBin // For Drive O:aBinForDrive [20] = sDriveBin // For Drive T:aBinForDrive [21] = sDriveBin // For Drive U:aBinForDrive [22] = sDriveBin // For Drive V:aBinForDrive [23] = sDriveBin // For Drive W:aBinForDrive [24] = sDriveBin // For Drive X:aBinForDrive [25] = "" // For Drive Y:aBinForDrive [26] = sDriveBin // For Drive Z:// *********************************************************function OnClick (ClickData) {// STEP 0: Introduce variables and sort out the full path of the deletion directory. var oFSO = new ActiveXObject ("Scripting.FileSystemObject") var nn = 0 var bContinue = true var sMessage = "" var sButtons = "" var nChoice = 0 var oDlg = DOpus.dlg var sPath = String (ClickData.Func.SourceTab.Path) var sDrive = DoExtractDrive (sPath) var sPathDel if (sDrive.substr (0, 2) == "\\\\") { sPathDel = aBinForDrive [0] // This corresponds to unmapped network drives } else { if (sDrive.charCodeAt (0) > 64 && sDrive.charCodeAt (0) < 91 && sDrive.substr (1, 1) == ":") sPathDel = aBinForDrive [sDrive.charCodeAt (0) - 64] // Number of the drive letter, with A: < - - > 1 } // STEP 1: Situations where the normal Windows Recycle Bin will be used, and where deletion is impossible. if (sDrive == "" || sPathDel == "" || sPathDel == undefined || sPathDel == null) { ClickData.func.command.RunCommand ("Delete") bContinue = false } if (bContinue) { if (DoExtractDrive (sPathDel) == "") // If the "BinForRecycle" path has no drive, add the source drive. sPathDel = sDrive + "\\" + sPathDel DOpus.Output ("sPath = " + sPath + " and sPathDel = " + sPathDel) if (sPath == sPathDel) { // Can't delete to the same directory. oDlg.title = "Operation has failed" oDlg.message = 'The "ForDeletion" directory cannot coincide with the source directory.' oDlg.icon = "warn" oDlg.buttons = "&OK" oDlg.Show bContinue = false } } // STEP 2: Enumerate the selected files and directories to an array and ask for confirmation. if (bContinue) { var oFiles = new DoArrayFromEnumerator (new Enumerator (ClickData.func.sourcetab.selected), nMaxDeletes) var aFiles = oFiles.aEnum for (nn = 0; nn < aFiles.length; nn++) sMessage = sMessage + "\r\n" + aFiles [nn].name if (aFiles.length == 0) { sMessage = "No files or folders have been selected for deletion." sButtons = "&OK" } else { if (aFiles.length == 1) { sMessage = "The following item has been selected for deletion to\r\n" + sPathDel + "\r\n" + sMessage sButtons = "&Delete this file|&Cancel" } else { sMessage = "The following " + aFiles.length + " items have been selected for deletion to\r\n" + sPathDel + "\r\n" + sMessage sButtons = "&Delete these files|&Cancel" } if (!(oFiles.bEnum)) sMessage = "Files will only be deleted in groups of " + nMaxDeletes + ".\r\n\r\n" + sMessage } oDlg.title = "Deletion to " + sPathDel oDlg.message = sMessage oDlg.icon = "" oDlg.buttons = sButtons var nChoice = oDlg.Show// STEP 3: Act on the choice. if (nChoice == 1) { var sToday = DoStandardDate (new Date) // This is the date deleted. var bPathCreated = DoCreatePath (sPathDel) if (bPathCreated) { for (nn = 0; nn < aFiles.length; nn++) { var sFileDateReverse = DoStandardDate (new Date (aFiles [nn].modify)) // The date modified as a reverse string. var sFileDate = '"20' + sFileDateReverse.substr (0, 6) + ' ' + sFileDateReverse.substr (7, 2) + ":" + sFileDateReverse.substr (9, 2) + ":" + sFileDateReverse.substr (11, 2) + '"' var sFileNameDel = aFiles [nn].name_stem + "_" + sToday + aFiles [nn].ext // Add the date stamp to the end of the filename. var sComment = "Comment:D" + sToday + " M" + sFileDateReverse + " " + sPath // Add Date deleted and date modified and location to the "User Description" metadata. DOpus.Output (sFileNameDel + " " + sComment) ClickData.func.command.RunCommand ('SetAttr ' + '"' + aFiles [nn] + '"' + ' Meta "' + sComment + '"') ClickData.func.command.RunCommand ('SetAttr "' + aFiles [nn] + '" Modified ' + sFileDate) ClickData.func.command.RunCommand ('Rename From "' + aFiles [nn] + '" To "' + sFileNameDel + '"') ClickData.func.command.RunCommand ('Copy Move "' + sPath + "\\" + sFileNameDel + '" to ' + sPathDel) } } } }DOpus.Output ("<- - - - - - - -") } // ********** FUNCTIONS BELOW ******************************function DoExtractDrive (sPath) { var sDrive = "" // The return value if sPath does not begin X: or \\NetworkComputer\ShareDriveName if (!(sPath == undefined)) { if (sPath.substr (1, 1) == ":" && sPath.charCodeAt (0) < 91 && sPath.charCodeAt (0) > 64) sDrive = sPath.substr (0, 2) // For example, if sPath = X:\AA\BB\CC then sDrive = X: if (sPath.substr (0, 2) == "\\\\") { // For \\ComputerB\DriveC\AA\BB\CC, sPath = \\ComputerB\DriveC var aPath = sPath.split ("\\") if (aPath.length > 3 && aPath [2].length > 0 && aPath [3].length > 0) sDrive = "\\\\" + sPath.split ("\\") [2] + "\\" + sPath.split ("\\") [3] // This would be \\ComputerB\DriveC } } return sDrive} // *********************************************************function DoCreatePath (sPath) { // Path starting at the drive and ending at the last subdirectory. var oFSO = new ActiveXObject ("Scripting.FileSystemObject") var aComponents = sPath.split ("\\") var bPathCreated = true var nFirstComponent = 0 var sPathPart = aComponents [0] if (sPath.substr (0, 2) == "\\\\") { var nFirstComponent = 2 var sPathPart = "\\\\" + aComponents [2] } if (DOpus.FSUtil.GetType (sPathPart) == "invalid") { // The drive must exist. var oDlg = DOpus.dlg oDlg.message = "The location " + sPathPart + " doesn't exist." oDlg.title = "Operation failed" oDlg.icon = "warn" oDlg.buttons = "&OK" oDlg.show bPathCreated = false } else { for (nn = 1 + nFirstComponent; nn < aComponents.length; nn++) { sPathPart = sPathPart + "\\" + aComponents [nn] if (DOpus.FSUtil.GetType (sPathPart) == "invalid") // Create each subdirectory in turn if it doesn't exist. oFSO.CreateFolder (sPathPart) } } return bPathCreated}// *********************************************************function DoArrayFromEnumerator (oEnum, nMax) { // oEnum is a collection, nMax is its optional maximum size with default 1000. var aEnum = new Array // Creates an array from all the elements in the collection. var nn = 0 var bEnum = true if (arguments.length < 2) var nMax = 1000 oEnum.moveFirst () nn = 0 while (!(oEnum.atEnd ()) && nn < nMax) { aEnum [nn] = oEnum.item () // This is the nth item. DOpus.Output (nn + ". " + aEnum [nn]) oEnum.moveNext () nn++ } if (!(oEnum.atEnd ())) { bEnum = false // There are more elements in the collection than have been added to the array. } this.aEnum = aEnum // The function has no return. Use it with new, then aFilesEnum.aEnum is the array and aFilesEnum.bEnum is the check. this.bEnum = bEnum // For example: var aFilesEnum = new DoArrayFrom Enumerator (oEnum, 1000)}// *********************************************************function DoStandardDate (oDate) { var dd = DoBuffer (oDate.getDate ()) var MM = DoBuffer (oDate.getMonth () + 1) var yy = DoBuffer (oDate.getFullYear ()) var HH = DoBuffer (oDate.getHours ()) var mm = DoBuffer (oDate.getMinutes ()) var ss = DoBuffer (oDate.getSeconds ()) var sReverseDate = yy + MM + dd + "@" + HH + mm + ss return sReverseDate}// *********************************************************function DoBuffer (nNumber, nLength) { // Two non-negative whole numbers var sNumber = -1 // Returns -1 if the algorithm below is not applied. if (arguments.length < 2) // Default is length 2 nLength = 2 if (nNumber >= 0 && Math.floor (nNumber) == nNumber && nLength >= 0 && Math.floor (nLength) == nLength) { sNumber = nNumber.toString () // This will be the buffered or truncated number. while (sNumber.length < nLength) // This bit adds zeroes at the front. sNumber = "0" + sNumber if (sNumber.length > nLength) // This bit truncates from the left. sNumber = sNumber.substr (sNumber.length - nLength) } return sNumber}