I'm trying to learn how to create my first DOpus Column Script by making a new column AvgFileSize that displays the average size of all files in a folder. Sounds simple enough. The problem is I can't figure out how to get the size of a folder. Here is my code so far:
Using GetSizes for this isn't going to work well. If the command object is not tied to a particular folder tab (as in the script currently), then it will end up picking the active tab/window and the results of the size calculation may be sent to and update the wrong file display entirely. If you start refreshing the column, then click on other windows, the size column stops populating in the window you expected it to calculate in.
While you can fix that using cmd.SetSourceTab, you then start to see progress dialogs while the sizes are calculated, which you would not want from a column. I don't think there is a way to suppress those currently.
The other issues can be solved by getting the information from the file display, but you either have a choice of unwanted progress dialogs or a fragile column that breaks if the tab becomes inactive.
Better to not use GetSizes here at all, and calculate the sizes in the script. This is easily done by recursing through the folders, which is easily done using the FSUtil.ReadDir method we provide for doing that. Examples of how to do that were in the script you used as a starting point. That script recurses the folders to calculate the file with the newest date, but the logic is similar if you want to add up all the file sizes.
It'd also make sense to count the files in the script in the same way, which makes sure the sizes and counts were calculated consistently. Also allows you to build in logic later which skips some folders or files (e.g. backups).
Note that we provide a FileSize object which handles 64-bit sizes and basic arithmetic. It's best to use that rather than a normal scripting language variable, as the scripting languages tend to have smaller limits on their integers.
I recently examined the GetSizes command for usage in script columns just like you, but as Leo already pointed out, it turned out to be the wrong tool for the job. Regarding size and other calculations for items in columns/status-bars, I also wished for more "ease". Some ideas here, some not new. o)
item.GetSize() method
script columns can decide wether to process folders or files first
scripts can return size (and duration e.g.) for status-bar usage or maybe fill custom status-bar codes
Anyway, for now I found the FilesystemObject to work quite well whenever folder sizes are required in scripts. It is quite fast, it is recursive and results are even cached at OS/filesystem level. Just don't expect your size columns to work like the native size columns, they won't, although you can specify "size" as column type. It was naive thinking of mine, but thinking twice, maybe not. o)
function GetFolderSize(path){
var fso = new ActiveXObject("Scripting.FileSystemObject");
var size = fso.GetFolder(path).Size;
if (!isNaN(parseInt(size,10))) return size;
return null;
}
This is what I had in mind, and gives you complete control or what is/isn't counted as well as the option of full recursion or not, with a single, simple loop:
var FolderPath = "C:\\"
var IsRecursive = false;
var TotalSize = DOpus.FSUtil.NewFileSize();
var TotalFiles = 0;
var FolderEnum = DOpus.FSUtil.ReadDir(FolderPath, IsRecursive);
while (!FolderEnum.complete) {
var FolderItem = FolderEnum.next;
if (!FolderItem.is_dir) {
TotalSize.Add( FolderItem.Size );
TotalFiles++;
}
}
DOpus.Output(TotalFiles + " files, " + TotalSize + " bytes");
Another difference: fso.GetFolder will fail if it encounters a sub-folder it cannot enter while DOpus.FSUtil.ReadDir skips over things it doesn't have access to.