AvgFileSize column script - can't get folder size

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:

Function OnInit(initData)

	initData.name = "Average File Size Column"
	initData.desc = "Column to show the average file size within a folder."
	initData.copyright = "© Waffles 2016"
	initData.version = "1.0"
	initData.default_enable = False

	With initData.AddColumn
    	.name = "AvgFileSize"
    	.label = "AvgFileSize"
    	.justify = "right"
    	.method = "OnAvgFileSize"
    End With

End Function

Function OnAvgFileSize(scriptColData)

    Dim cmd

    Set cmd = DOpus.Create.Command

    With scriptColData
        If .item.is_dir Then
            If Not .item.got_size Then
                cmd.AddFile .item
                cmd.RunCommand "GetSizes"
            End If
            .value = cmd.results.result & " / " & .item.got_size & " / " & .item.size & " / " & .item.metadata.other.filecounttotal
        End if
    End With

End Function

And here is how it looks:

As you can see I've put debug code in the column so I can see what's going wrong. Breaking down the results:

1 / False / 0 / 2

  • cmd.results.result =1 .......................... means GetSizes succeeded
  • item.got_size = False .......................... means we haven't run GetSizes yet
  • item.size = 0 ..................................... means we haven't run GetSizes yet
  • item.metadata.other.filecounttotal = 2 ... means GetSizes succeeded!?

Is this a bug in DOpus 11.17? Or am I just doing it wrong? :angry:

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.

That fixed it! Thanks for all your amazing help Leo. And I agree with tbone - an item.GetSize method would be useful.

I have shared my script on the forum here :arrow_right: