How to make .exe files sort above other files, without breaking name sorting?

How to keep folders always on top, but also make .exe files sort above other non-folder items (while still sorting by name within each group)

Easiest way is probably to make an evaluator "Is exe?" column, then do a multi-column sort with that as the first column and Name as the second.

:smiling_face_with_tear:It’s a little difficult for me.

This is suboptimal and a little ugly but you could group using something like the following script. I use many categories but i deleted them for this example. I wouldn't add the column itself, rather i would group according to doc category in folder format settings.

// DocCategory – fixed group order, easy category edits, optional auto-collapse
// Language: JScript (Directory Opus Script Add-in)
// J.Fourie

var SETTINGS = {
    autoCollapseOnFolderChange: false,

    // Column name/label (change if you make variants).
    columnName: "DocCategory",
    columnLabel: "Doc Category",

    // Define your categories here, in the order you want them grouped.
    // 1) "Folders" is handled automatically (item.is_dir) — keep it first.
    // 2) For simple extension-based categories, just add to `exts`.
    // 3) For logic-based categories, supply a `match(item, ext)` function that returns true/false.
    categories: [
        { name: "Folders",   special: "folders" }, // reserved; handled by item.is_dir
		{ name: "Exe",       exts: [".exe", ".shortcut"] },
        // NOTE: "Other" is the catch-all. Keep it last.
        { name: "Other",     exts: [] }
    ]
};

// ---------- INTERNALS (you generally don't need to touch below this line) ----------

// Build a quick lookup from extension -> category name for fast classification.
var EXT_TO_CAT = (function buildExtMap(){
    var map = {};
    for (var i = 0; i < SETTINGS.categories.length; i++) {
        var c = SETTINGS.categories[i];
        if (c.exts && c.exts.length) {
            for (var j = 0; j < c.exts.length; j++) {
                var e = ("" + c.exts[j]).toLowerCase();
                map[e] = c.name;
            }
        }
    }
    return map;
})();

// Build the explicit group order string for the column (semicolon-separated).
function getGroupOrderString() {
    var names = [];
    for (var i = 0; i < SETTINGS.categories.length; i++) {
        names.push(SETTINGS.categories[i].name);
    }
    return names.join(";");
}

// Return the category name for an item.
function classifyItem(item) {
    if (item.is_dir) return "Folders";

    var ext = (item.ext || "").toLowerCase();
    if (EXT_TO_CAT.hasOwnProperty(ext)) return EXT_TO_CAT[ext];

    // Fallback to any function-based category rules (rare case)
    for (var i = 0; i < SETTINGS.categories.length; i++) {
        var c = SETTINGS.categories[i];
        if (typeof c.match === "function") {
            try {
                if (c.match(item, ext) === true) return c.name;
            } catch(e) {
                // ignore match errors; fall through to Other
            }
        }
    }
    return "Other";
}

// ---------------- Opus Hooks ----------------

function OnInit(initData) {
    initData.name = "DocCategory";
    initData.version = "1.4";
    initData.desc = "Custom document category column with fixed order and folders on top (auto-collapse optional)";
    initData.default_enable = true;
    initData.min_version = "12.0";
	initData.group = "Column";

    var col = initData.AddColumn();
    col.name = SETTINGS.columnName;
    col.method = "OnDocCategory";
    col.label = SETTINGS.columnLabel;
    col.justify = "left";

    // We supply explicit group order and group labels; no auto-grouping.
    col.autogroup = false;
    col.grouporder = getGroupOrderString();
    col.autorefresh = true;
}

function OnDocCategory(colData) {
    var label = classifyItem(colData.item);
    colData.value = label; // visible cell text
    colData.group = label; // group header text
}

// OPTIONAL: Auto-collapse groups on folder change (so "Other" begins collapsed).
// This affects all groups (Opus limitation). Toggle via SETTINGS.autoCollapseOnFolderChange.
function OnAfterFolderChange(data) {
    if (!SETTINGS.autoCollapseOnFolderChange) return;
    try {
        var cmd = DOpus.Create.Command();
        cmd.SetSourceTab(data.tab);
        // Collapse all groups in this tab. There is currently no official way
        // to collapse a single named group (e.g., "Other") only.
        cmd.RunCommand("Set GROUPCOLLAPSE=Off");
    } catch (e) {
        // swallow; nothing critical
    }
}

Leo's idea in a few easy steps:

  • Create a column (we show the name because it looks nicer)

operation == "sort" ? ext == "exe" : name
XML
<?xml version="1.0"?>
<evalcolumn align="0" attrrefresh="no" autorefresh="no" blurrable="no" customgrouping="no" foldertype="all" keyword="IsExe" maxstars="5" namerefresh="no" nocache="no" reversegroups="no" reversesort="no" supportmarkup="no" title="IsExe" type="0">operation == &quot;sort&quot; ? ext == &quot;exe&quot; : name</evalcolumn>
  • Show the column in the FD
Set COLUMNSTOGGLE=eval:IsExe
  • Multi-sort by new column and name
Set SORTBY=eval:IsExe,name

Thank you very much to Leo for the guidance and to lxp for the answer. It's already being used, and I'm very happy about it.