Yesterday I posted a script command in the scripts section of the forum: Command: RenameFolderAddCount
It uses ReadDir() to recursively step through subfolders and works as expected so far, but..
If I use ReadDir() recursively (by scripting) more than once in non-recurse mode, a final "RENAME FROM.. TO.." on a top-level folder results in an "Access denied" message:
This does not happen if I use ReadDir() and it's builtin recurse option and also not if ReadDir() is called on that folder only once (in non-recurse mode).
So it's my own recursion implementation that leads to that problem it seems, but actually I don't see why that should happen, it does not stall or run endless, it exactly yields the results I am after.
I tried to resolve things by nulling all enumerators in use and calling the RENAME out of the loop of while(!enumerator.complete){...} etc., but it does not help.
Now that ReadDir() has that builtin recurse mode, I wonder if this is for convinience only or if it intentionally exists to get around things I encounter? I doubt that though! o)
Maybe anybody has a clue why that happens? The problem can be seen when calling "RenameFolderAddCount deepness=9999" to activate my own recursion.
Thx! o)
I put some smallish demo-code together to make things easier for you and me, find it attached and in the code-box.
The script adds a command "ReadDirAndRename", which gives "Access Denied" whenever used with a folder that contains subfolders (so ReadDir() was called more than once).
///////////////////////////////////////////////////////////////////////////////
function OnInit(data){
data.name = "Command.Folder: ReadDirAndRename";
data.default_enable = true;
var cmd = data.AddCommand();
cmd.name = "ReadDirAndRename";
cmd.method = "Command_ReadDirAndRename";
cmd.label = "ReadDirAndRename";
}
///////////////////////////////////////////////////////////////////////////////
function Command_ReadDirAndRename(data) {
var foldersEnum = new Enumerator(data.func.sourcetab.selected_dirs);
while (!foldersEnum.atEnd()) {
var folder = foldersEnum.item(); foldersEnum.moveNext();
Crawl(folder.realpath);
var cmd = 'RENAME PATTERN=* FROM="'+folder.realpath+'" TO="* (x)"';
data.func.command.RunCommand(cmd);
}
}
//////////////////////////////////////////////////////////////////////////////
function Crawl(path){
DOpus.Output("Crawling ["+path+"]..");
var folderEnum = DOpus.FSUtil.ReadDir( path, false);
while(!folderEnum.Complete){
var childItem = folderEnum.Next();
if (childItem.is_dir)
Crawl(childItem.realpath);
}
} Command.Folder_ReadDirAndRename.js.txt (1.07 KB)
Add a call to CollectGarbage(); before the line that runs the command. That will force JScript to release the out-of-scope objects it is holding on to.
(CollectGarbage() is a Microsoft extension to JavaScript, and not technically guaranteed to do anything, but it seems to solve the problem.)
We'll also add a folderEnum.Close(); method in the next update, which may be needed for Perl/Python/etc. and will also be more efficient for JScript (since doing a whole GC to release one object is overkill).
Yes, it does the trick here too! Thank you very much for your investigation and research! o)
I was about to reimplement the Crawl() method to base on "Scripting.FilesystemObject", but prefer it this way of course! o)