AddFilesFromFolder, ReadDir (or other collection) sort order

Noobie questions.

  1. At the moment, it looks like collections created by ReadDir and AddFilesFromFolder are sorted by name_stem. Is that correct?

  2. Is there a mechanism for specifying a sort order for file collections created in this way? For instance, before applying a rename action that adds a number to the file name, one could want the collection of files to be passed in a different order.

  3. More generally, when working with a collection, for instance selected_files, is there an easy way to change the default sort order by which they get enumerated (for instance ext first, name_stem second, or some metadata property)?
    Does one have to define a custom sort function, and if so, can it operate on the selected_files collection, or does it first have to be fanned into a different kind of object?

Collections don't maintain a sort order of their own, the sort order is set by the folder format as for any other folder.

At times, I can imagine wanting to set the order of a collection manually -- especially when adding not from a selection but using something like ReadDir or AddFilesFromFolder.

The "long way" (fanning into a different structure) seems to work. My example is contrived and probably not optimal. But something like this can be useful when files need to be renamed one by one, or passed to a command as a custom-sorted collection.

Usage of Example

  • When some files are selected, this button outputs a list to the Other Logs, with files sorted by name length ASC and name DESC.
  • If the Run line is uncommented, the files are renamed one by one (something I've been wanted to play with).
  • Yes they could be renamed in bulk by adding them via AddFile and doing a bulk run on a different preset.
// Main script entry point. DO passes the ClickData object to the function.
function OnClick(clickData) {

    // Open the other logs
    clickData.func.command.RunCommand("Set UTILITY=otherlog")

    // selected_files is a collection. It cannot be sorted.
    var selected_files = clickData.func.sourcetab.selected_files

    // In order to sort the files, create an array
    var fileCollection = []
    var enumFiles = new Enumerator(selected_files)
    enumFiles.moveFirst()
    while (!enumFiles.atEnd()) {
        currentFile = enumFiles.item()
        fileCollection.push(currentFile)
        // if you want an array with the files and some custom computed item, do something like
        // fileCollection.push( {item:currentFile, custom:something} )
        enumFiles.moveNext()
    }


    DOpus.Output("\nSort by name length ASC + name DESC")
    fileCollection.sort(function (a, b) {
        if (a.name.length - b.name.length != 0) {
            return a.name.length > b.name.length ? 1 : -1
        }
        else {
            return b.name_stem.toLowerCase() > a.name_stem.toLowerCase() ? 1 : -1
        }
    })

    var cmd = DOpus.Create.Command()

    DOpus.Output("Custom sort: name length ASC + name DESC")
    // Rename files one by one
    // To actually rename, uncomment the cmd.Run() line
    for (var i = 0; i < fileCollection.length; i++) {
        cmd.AddLine('Rename PATTERN ^(.*)$ TO "' +
            i.toString() + ' \\1" REGEXP')
        cmd.AddFile(fileCollection[i])
        // cmd.Run()
        cmd.Clear()
        cmd.ClearFiles()

        DOpus.Output((i+1).toString() + " - " + fileCollection[i].name)
    }
}

Custom Sort.dcf (3.25 KB)

I think Jon's answer was about Opus File Collections (also what I thought this thread would be about at first), but we're talking about script-collection-objects containing files, which are different.

If you want the list of files returned by ReadDir or AddFilesFromFolder to be sorted in a different way, then yes you have to re-sort it, as you're doing.

Thanks Leo, good to know I'm on the right track. :slight_smile: