Sending list of paths to external program either fails or takes too long

My goal is to send selected lister items to foobar2000, but only files which match the Music file type group.

This script attempts to do that. In summary: If a selected item is a directory / symbolic link / junction, recursively check if its files are part of the file type group. Also check all other selected items (which are likely to be files). In both cases, if a file is part of the file type group, add it to a vector of qualifying files. Lastly, pass the list of qualifying files to foobar2000.

function is_in_group(item) {
    if (item.ingroup("disp:Music")) {
        return true;
    }
}

function OnClick(clickData) {
    var factory = DOpus.create();
    var source_tab = clickData.func.sourcetab;
    var selected_items = source_tab.selected;

    var files_in_group = factory.vector;
    for (var i = 0; i < selected_items.count; i++) {
        var selected_item = selected_items(i);

        if (selected_item.is_dir || selected_item.is_symlink || selected_item.is_junction) {
            var dir_enum = DOpus.fsutil.readdir(selected_item, "r");
            var dir_items = dir_enum.next(-1);

            for (var j = 0; j < dir_items.count; j++) {
                if (is_in_group(dir_items(j))) {
                    files_in_group.append([dir_items(j)]);
                }
            }
        }
        else {
            if (is_in_group(selected_item)) {
                files_in_group.append([selected_item]);
            }
        }
    }

    var cmd = factory.Command;
    cmd.addfiles(files_in_group);
    cmd.addline("@async:\"C:\\Program Files (x86)\\foobar2000\\foobar2000.exe\" {allfilepath}");
    cmd.run();
}

The script executes successfully on some directories, but when running it on large directories (a few thousand files):

C:\Program Files (x86)\foobar2000\foobar2000.exe

The filename or extension is too long.

I'm not sure who's producing the error (foobar2000 or Opus) but the process of the pop-up is dopus.exe. Similarly unsure whether it's the sheer number of files in a large directory, or the depth of it which causes the issue.

The only solution I've found is to create many AddLines(), but the performance is poor as many foobar2000.exe processes are created and it ultimately takes much too long to loop through:

for (var i = 0; i < files.count; i++) {
    cmd.addline("@async:\"C:\\Program Files (x86)\\foobar2000\\foobar2000.exe\" \"" + files(i) + "\"");
}

I wouldn't be surprised if there's a better and simpler way of doing what I'm attempting to do. Any help is appreciated, thanks!

Windows itself has a command-line length limit, which you're probably hitting. You won't be able to send all the filepaths on a single command line.

If Foobar can take the list in a text file, that's probably the best way. (In fact, it can; you can generate a simple .m3u playlist for this.)

1 Like

Have you tried foobar2000.exe {filepath}? Seems to work on files, folders, and junctions, and includes all subdirectories.

1 Like

This is a great idea! A temporary playlist should do the trick :slightly_smiling_face:

Interesting! Without needing to introduce a loop, changing {allfilepath} to {filepath} does correct the issue, however the enumeration of files to pass onto foobar2000 still takes Opus too much time.

Using a playlist looks to be the ideal solution and will reduce the wait-time down to just the time it takes foobar2000 to process the imported playlist of its paths.

I meant the command to be used on its own, not in a script, and let foobar2000 do all the processing.