EverythingFolderSize (Use Everything to calculate folder sizes)

Last update: 2024-04-30

  • Simplified installation
  • Added configuration dialog
  • Added toolbar
  • Merged script files
  • Enhanced logging/debugging
  • Automatic removal of temp files

This add-in generates a custom column EverythingFolderSize that uses Everything to display folder sizes.

Opus 12 will display folder sizes almost instantaneously, just like Opus 13.

This functionality (and more) is natively available in Opus 13. Users of Opus 13 can benefit from this add-in if they want to try out other versions of Everything (1.5 alpha or any portable installation) or need a "second opinion".

Keep in mind that both the script and Everything use caches for the folder sizes. While refreshing these caches is typically fast and reliable, it's crucial to check with Opus' internal functions before performing any critical actions, such as deletion, based on the values in the column.

How to set up and use

:one:
Save EverythingFolderSize.dop to   

%appdata%\GPSoftware\Directory Opus\Buttons

and ColumnEverythingFolderSize.js.txt to   

%appdata%\GPSoftware\Directory Opus\Script AddIns

If you are upgrading from a 2023 version, remove EventUpdateEverythingFolderSize.js.txt.

:two:
Turn on the EverythingFolderSize toolbar with

Toolbar NAME=EverythingFolderSize TOGGLE

or via the Customize dialog.

:three:
Download both Everything and Everything Command-line Interface.

:four:
Install Everything and unpack es.zip.

:five:
If you run Everything 1.4:

  • Copy es.exe to /programfiles\Everything
  • Check Index folder size in Everything Options

:six:
If you run Everything 1.5a:

  • Copy es.exe to /programfiles\Everything 1.5a
  • Add a line (or change) alpha_instance=0 in Everything-1.5a.ini.

:seven:
If you run Everything 1.5a or a Portable Installation:

  • Click the Configuration button and update the path to es.exe. Any notation Opus understands is fine.

:eight:
Click the EverythingFolderSize button to toggle the column.

:nine:
(Optional) The toolbar comes with two buttons (v12 and v13) that turn the script on and off. Remove the one that doesn't match your version.

Troubleshooting

Does Everything work on its own? Are the indexes ok?

Refresh the file display (F5).

Click the Configuration button and set the logging to Standard. Turn the script off and on. Check the log.

If the script is disabled, the column will keep displaying the last received values, and any changes will not be reflected.

If the column fails to receive valid data from Everything, it will remain empty.

Things you might enjoy reading

What are aliases?

How to use buttons and scripts from this forum

The script's inner workings

JScript
function OnInit(initData) {
    initData.name = 'EverythingFolderSize';
    initData.version = '2024-04-30';
    initData.url = 'https://resource.dopus.com/t/everythingfoldersize-use-everything-to-calculate-folder-sizes/44281';
    initData.desc = 'Use Everything to display folder sizes';
    initData.default_enable = true;
    initData.min_version = '12.0';

    initData.config_desc = DOpus.Create().Map();
    initData.config_groups = DOpus.Create().Map();

    initData.config_desc('exeES') = 'Enter full path to es.exe';
    initData.config_groups('exeES') = '1 - Paths';
    initData.config.exeES = '/programfiles\\Everything\\es.exe';
    // initData.config.exeES = '/programfiles\\Everything 1.5a\\es.exe';

    // Everything 1.4: Check "Index folder size" in Tools-Options-Indexes
    // Everything 1.5: Everything-1.5a.ini needs to contain this line: alpha_instance=0

    initData.config_desc('colType') = 'Set column type';
    initData.config_groups('colType') = '2 - Columns';
    initData.config.colType = DOpus.Create.Vector(0,
        'size',
        'number');

    initData.config_desc('logLevel') = 'Set level of logging';
    initData.config_groups('logLevel') = '3 - Logging';
    initData.config.logLevel = DOpus.Create.Vector(0,
        'none',
        'standard',
        'max');
}

function OnAddColumns(addColData) {
    var col = addColData.AddColumn();
    col.name = 'EverythingFolderSize';
    col.header = 'EFS';
    col.method = 'OnColumn';
    col.justify = 'right';
    col.type = Script.config.colType ? 'number' : 'size';
    col.autorefresh = 2;

    var exeES = fsu.Resolve(Script.config.exeES);

    if (fsu.Exists(exeES)) {
        Log(1, 'exeES:    ' + exeES);
    } else {
        Log(1, 'exeES:    ' + exeES);
        Log(1, '          <font color=#FF0000>File not found!</font>');
    }

    if (!fsu.Exists(exeES.pathpart + '\\Everything.exe') &&
        !fsu.Exists(exeES.pathpart + '\\Everything64.exe')) {
        Log(1, '          <font color=#FF0000>Everything.exe/Everything64.exe not found!</font>');
    }

    Log(1, 'logLevel: ' + Script.config.logLevel);
    Log(1, 'colType:  ' + Script.config.colType);
}

function OnColumn(scriptColData) {
    var item = scriptColData.item;
    if (item.is_dir) {
        if (item.path.drive == 0) return;
        var dirVar = 'EFS"' + item + '"';
        if (!DOpus.vars.Exists(dirVar)) return;
        scriptColData.value = DOpus.vars.Get(dirVar);
    } else {
        scriptColData.value = item.size;
    }
}

function OnOpenTab(openTabData) {
    if (!openTabData.tab) {
        Log(1, 'OnOpenTab:            !openTabData.tab is true');
        return;
    }

    if (openTabData.tab == undefined) {
        Log(1, 'OnOpenTab:            openTabData.tab == undefined');
        return;
    }

    cmd.SetSourceTab(openTabData.tab);
    if (!cmd.IsSet('Set COLUMNSTOGGLE=scp:EverythingFolderSize/EverythingFolderSize')) {
        Log(1, 'OnOpenTab:            No column "EverythingFolderSize" in this file display... nothing to do!');
        return;
    }

    if (!openTabData.tab.path) {
        Log(1, 'OnOpenTab:            !openTabData.tab.path is true');
        return;
    }

    if (openTabData.tab.path == undefined) {
        Log(1, 'OnOpenTab:            openTabData.tab.path == undefined');
        return;
    }

    if (!String(openTabData.tab.path)) {
        Log(1, 'OnOpenTab:            <font color=#FF0000>Empty path!</font>');
        return;
    }

    Log(1, 'OnOpenTab:            <font color=#00FF00>Calling QueryEverything...</font>');
    QueryEverything(openTabData.tab.path);

    Log(1, 'OnOpenTab:            <font color=#00FF00>... done!</font>');
}

function OnBeforeFolderChange(beforeFolderChangeData) {
    if (!beforeFolderChangeData.tab) {
        Log(1, 'OnBeforeFolderChange: no beforeFolderChangeData.tab');
        return;
    }

    cmd.SetSourceTab(beforeFolderChangeData.tab);
    if (!cmd.IsSet('Set COLUMNSTOGGLE=scp:EverythingFolderSize/EverythingFolderSize')) {
        Log(1, 'OnBeforeFolderChange: No column "EverythingFolderSize" in this file display... nothing to do!');
        return;
    }

    if (!beforeFolderChangeData.path) {
        Log(1, 'OnBeforeFolderChange: no beforeFolderChangeData.path');
        return;
    }

    if (beforeFolderChangeData.path.drive == 0) {
        Log(1, 'OnBeforeFolderChange: beforeFolderChangeData.path.drive == 0');
        return;
    }

    if (!String(beforeFolderChangeData.path)) {
        Log(1, 'OnBeforeFolderChange: <font color=#FF0000>Empty path!</font>');
        return;
    }

    Log(1, 'OnBeforeFolderChange: Calling QueryEverything...');
    QueryEverything(beforeFolderChangeData.path);
}

function QueryEverything(path) {
    var exeES = fsu.Resolve(Script.config.exeES);

    if (!fsu.Exists(exeES)) {
        Log(1, 'exeES: ' + exeES);
        Log(1, '       <font color=#FF0000>File not found!</font>');
        return;
    }

    var expPath = fsu.GetTempFilePath();

    var cmdLine = '"' + exeES + '"' +
        ' -size' +
        ' -no-header' +
        ' -export-csv "' + expPath + '"' +
        ' -parent "' + path + '"' +
        ' /ad';

    Log(1, cmdLine);
    wsh.Run(cmdLine, 0, true);

    var expFile = fsu.GetItem(expPath).Open();
    var arr = stt.Decode(expFile.Read(), 'utf8').split('\r\n');
    expFile.Close();

    var re = /(\d+),(.*)/;

    for (var i = 0; i < arr.length; i++) {
        var line = arr[i].match(re);
        if (!line) continue;
        if (line.length != 3) continue;
        var size = line[1];
        var dirVar = 'EFS' + line[2];
        DOpus.vars.Set(dirVar, size);
        Log(2, dirVar + '\t' + size);
    }

    if (!Script.config.logLevel) {
        cmd.RunCommand('Delete' +
            ' FILE="' + expPath + '"' +
            ' QUIET' +
            ' NORECYCLE');
        // DOpus.Output('Deleted: ' + expPath);
    }
}

function Log(level, str, time) {
    var logLevel = Script.config ? Script.config.logLevel : 2;
    if (!logLevel) return;
    if (!level) return;
    if (level > logLevel) return;
    if (time) {
        var currTime = DOpus.Create().Date();
        str = padTime(currTime + currTime.ms - time - time.ms) + ' ' + str;
    }
    DOpus.Output(str);
}

var cmd = DOpus.Create().Command();
var stt = DOpus.Create().StringTools();
var fsu = DOpus.FSUtil();
var wsh = new ActiveXObject('WScript.Shell');
12 Likes

Thank you ever so much, Ixp, your efforts are greatly appreciated! This isn't so common these days.

It does work and I really love to be able to have the persistent column that auto-calculates vs. having to trigger it, but unfortunately, it is very clunky in so far as it takes a lot of CPU time (and I have a 13th Gen Intel), so the CPU is pretty much fully occupied all the time if I keep moving through folders. Also, it takes significantly longer as with the TC Everything integration, which also needs no CPU at all and it really works instantaneously. I've tested it with both 1.4 and 1.5 alpha, so it shouldn't be related to that. I suspect it has to do with the CLI es.exe. I've tried both versions of your code btw., I noticed your edit.

If you wanna take a look at the TC implementation, you just have to add alpha_instance=0 to the Everything.ini and add the path to Everything.exe into the wincmd.ini (Everything=), tick 'Index folder size' in Everything options under 'Indexes' and tick 'Everything' in TC in configuration under 'Operation' and 'Calculate space occupied by subdirectories' close to the bottom of the dialog. Also, Everything has to be running before you fire up TC.

See these two forum threads if you're interested and want some more context:
https://ghisler.ch/board/viewtopic.php?t=51534
https://www.ghisler.ch/board/viewtopic.php?p=344501#p344501

It works flawlessly, but DOpus is so much better than TC in almost every other regard. I will still be using TC for that single feature, though, since it is invaluable for me.

Yes. es.exe gets called once per folder. Calling it once per tab and storing the results in variables should be faster. I'll check how fast TC is - nothing beats a good benchmark :slight_smile:

You can get the information you need in one ES.exe call.

Haven't looked at your script/ plugin/?, so this might be a mismatch, but the following will report the sizes of all folders directly under "C:\Program Files":

es.exe   folder:parent:"C:\Program Files"   -name   -size   -sizeformat 1   -csv

Example output:

Name,Size
"7-Zip",5735904
"Common Files",43432000
"CONEXANT",320477376
"Directory Opus",114135935
"Dolby",27502975
"Everything 1.5a",9622508
"Internet Explorer",2538218
"LinkShellExtension",511152
"Microsoft Update Health Tools",1936112
"ModifiableWindowsApps",0
"Mozilla Firefox",227615557
"MSBuild",25757
"Reference Assemblies",36844201
[...]

There are more options for finetuning -- let me know if you need more info -- but this should get you close.

Note: For "flat folders" [1] (EDIT: it is called: ) Flat View you need a differrent search syntax. Something like:

es.exe   folder:"c:\program files\"   -full-path-and-name   -size   -sizeformat 1   -csv

Note the \ at the end of the foldername; this prevents the "Program Files (x86)" to be caught too.



[1] Probably called different; Total Commander calls it Branch View; XYplorer calls it Branch View/ Flat View.
It is the content of a folder and its subfolders in one flat list.

1 Like

Yes. But Opus calls the script once per item in the tab.

Improved version that only makes one call per tab. Slightly faster :wink:

Content consolidated in first posting

The script stores the data from Everything in variables remaining available until Opus is shut down. Opus will get an update on every folder change. This can be turned off with the button below. Note that the columns will still display the last received values and that any changes will not be reflected! Folders read for the first time with the update mechanism turned off will be shown with size zero. As I mentioned in the intro: please double-check!

function OnInit(initData) {
    initData.name = 'UpdateEverythingFolderSize';
    initData.version = '2023-04-25';
    initData.copyright = '';
    initData.url = 'https://resource.dopus.com/t/everythingfoldersize-use-everything-to-calculate-folder-sizes/44281';
    initData.desc = '';
    initData.default_enable = true;
    initData.min_version = '12.0';
}

function OnBeforeFolderChange(beforeFolderChangeData) {
    var fsu = DOpus.FSUtil();
    var exeES = fsu.Resolve('/programfiles\\Everything\\es.exe');
    var wsh = new ActiveXObject('WScript.Shell');
    var stt = DOpus.Create().StringTools();

    var exportFile = fsu.GetTempFilePath();

    var cmdLine = '"' + exeES + '"' +
        ' -size' +
        ' -no-header' +
        ' -export-csv "' + exportFile + '"' +
        ' -parent "' + beforeFolderChangeData.path + '"' +
        ' /ad';

    // DOpus.Output(cmdLine);
    wsh.Run(cmdLine, 0, true);

    var vec = DOpus.Create().Vector(stt.Decode(fsu.GetItem(exportFile).Open().Read(), 'utf8').split('\r\n'));

    for (var e = new Enumerator(vec); !e.atEnd(); e.moveNext()) {
        var line = e.item().split(',');
        if (line.length != 2) continue;
        var size = line[0];
        var dirVar = 'EFS' + line[1];
        DOpus.vars.Set(dirVar, size);
    }
}
function OnInit(initData) {
    initData.name = 'EverythingFolderSizeVars';
    initData.version = '2023-04-25';
    initData.copyright = '';
    initData.url = 'https://resource.dopus.com/t/everythingfoldersize-use-everything-to-calculate-folder-sizes/44281';
    initData.desc = '';
    initData.default_enable = true;
    initData.min_version = '12.0';
}

function OnAddColumns(addColData) {
    var col = addColData.AddColumn();
    col.name = 'EverythingFolderSizeVars';
    col.header = 'EverythingFolderSizeVars';
    col.label = 'EverythingFolderSizeVars';
    col.method = 'OnColumn';
    col.justify = 'right';
    col.type = 'size';
}

function OnColumn(scriptColData) {
    var item = scriptColData.item;
    if (!item.is_dir) return;
    if (item.path.drive == 0) return;

    var dirVar = 'EFS"' + item + '"';
    scriptColData.value = DOpus.vars.Exists(dirVar) ? DOpus.vars.Get(dirVar) : 0;
}

Save these

EventUpdateEverythingFolderSize.js.txt
ColumnEverythingFolderSizeVars.js.txt

to

%appdata%\GPSoftware\Directory Opus\Script AddIns

Toggle the column with

Set COLUMNSTOGGLE="scp:EverythingFolderSizeVars/EverythingFolderSizeVars(!,a,0)"
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="label" label_pos="right" textcol="none">
	<label>EverythingFolderSizeVars</label>
	<icon1>#newcommand</icon1>
	<function type="normal">
		<instruction>Set COLUMNSTOGGLE=&quot;scp:EverythingFolderSizeVars/EverythingFolderSizeVars(!,a,0)&quot;</instruction>
	</function>
</button>

Toggle the event that updates the folder sizes with

@toggle:invert
Prefs SCRIPTDISABLE="EventUpdateEverythingFolderSize.js*,toggle"
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" label_pos="right" textcol="none">
	<label>UpdateEverythingFolderSize</label>
	<icon1>#filterfolder</icon1>
	<function type="normal">
		<instruction>@toggle:invert</instruction>
		<instruction>Prefs SCRIPTDISABLE=&quot;EventUpdateEverythingFolderSize.js*,toggle&quot;</instruction>
	</function>
</button>
3 Likes

Masterful, Ixp, now it's as speedy and resource-friendly as in TC. Thanks so much, one app less to worry about! :smiley:

Yes, it really is a difference like day and night. Didn't see that coming, honestly. But a nice surprise once in a while is ok :slight_smile:

hmm. I can't get this to work. I installed the 64-bit version of Everything and I noticed the filename is:
C:\Program Files\Everything\Everything.exe

So I replaced:

var exeES = fsu.Resolve('/programfiles\\Everything\\es.exe');

with

    var exeES = fsu.Resolve('c:\\program files\\Everything\\Everything.exe');

but the EverythingFolderSizeVars column still shows 0 bytes :man_shrugging:

What am I doing wrong?

Everything.exe and es.exe are not the same. See Command Line Interface - voidtools which also links to where you can download es.exe near the top.

1 Like

Furthermore: Everything itself must be running in the background when using EverythingFolderSize:
ES.exe sends the search-query to Everything, which looks in its database and sends the matching results back to ES.

1 Like

It looks like this hyperlink does not contain an url?

Ah ok. That makes sense.
Except it's still not working for me. 'Everything' is installed and works as it should. But the EverythingFolderSizeVars column stays blank.

I've tried:

    var exeES = fsu.Resolve('/programfiles\\Everything\\es.exe');
    var exeES = fsu.Resolve('/program files\\Everything\\es.exe');

and

    var exeES = fsu.Resolve('C:\\Program Files\\Everything\\es.exe');

Not sure what the correct syntax is. I'm a bit new to scripts and buttons as you might be able to tell...

Oops. Yes. Fixed!

1 Like

The process is quite intransparent, let me try and help you. First, you open this post as reference:

What you do (as far as I understand it and it's working flawlessly for me now) is the following:

You download the item under 'Download Everything Command-line Interface', this gives you the es.exe you need to then put into Program Files/Everything:
https://www.voidtools.com/downloads/#cli

You make sure Everything is running, I suggest you activate Everything as a service if you haven't already (you can use this method with either 1.4 or 1.5 alpha, you just have to make sure only one instance is running and you have alpha_instance=0 set in everything.ini.

Now you download the two text files Ixp attached above and put them in the posted folder 'Script AddIns'.

Then right click on DOpus title par and activate customize mode through 'Customize...'.

Righ-click on the toolbar and select either 'New -> New Button' or 'Insert New -> New Button' depending on where you click.

Create two different buttons. Right-click on each button and click 'Edit...', click 'Advanced...', pick 'Script Function' under 'Function', select 'JScript' under 'Script Type' and replace the text below with the content of the two green code boxes above. Then you can remove the buttons from the toolbar (I clicked them once, but I don't think you have to do that, it's just to add the code to DOpus' DB). Deactivate customize mode.

Now you can right-click on the columns and tick 'EverythingFolderSizeVars' under 'Columns -> Script' and voilà (I changed the label of EverythingFolderSizeVars, so the column isn't too wide). Now you can optionally add the XML buttons to toggle visibility and refresh or you just leave the column activated permanently.

2 Likes

Thank you for trying to help me.

I have Everything 64-bit installed and running as a service. It works fine as I am able to use the Everything GUI to filter the file list as expected.

I have copied the es.exe file into the Program Files\Everything folder.

There is no alpha_instance=0 present in the everything.ini file.
I see only
allow_multiple_instances=0

I added alpha_instance=0 also, but it made no difference.

I have downloaded and put the scripts into the
\AppData\Roaming\GPSoftware\Directory Opus\Script AddIns folder.
I noticed they have a .js.txt extension, I even tried changing the extension to just .js, but still no go.

I have created the buttons by pasting in the XML shown above.
The show/hide column button works as expected.

The UpdateEverythingFolderSize button however does nothing.

As an aside, after installing Everything last night, my machine hung instead of going to sleep like it normally does when I finished for the day... It normally never does this. Everything is the only new software I installed yesterday.

Both are ok

Is the column empty or are the values zero?

All it does is toggle this check box:

Before, when I mistakenly had
var exeES = fsu.Resolve('c:\program files\Everything\Everything.exe');
it was zeros.
When I corrected it to
var exeES = fsu.Resolve('/programfiles\Everything\es.exe');
it's empty

You are looking at the correct column EverythingFolderSizeVars, right?

Please uncomment line 26 in EventUpdateEverythingFolderSize.js

// DOpus.Output(cmdLine);

You should then see something in the logs when changing or refreshing the tab.

Oh, I'm sorry, you only need the alpha_instance=0 if you're using 1.5 alpha of Everything. You have to copy the cli.c with the es.exe, you probably forgot that. When I rename cli.c, I also get 0s as a result. EDIT: Never mind, I had the Refresh button disabled, that's why it didn't work without cli.c. :stuck_out_tongue: Maybe you have that disabled somehow?