Passing file paths: FORCE quotes?

Looking at why I keep running into trouble passing selected files to PotPlayer, I found out that, somehow, it seems to require quotes around the filenames passed to it.
File paths with spaces in them, the use of "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" {allfilepath} /sort works fine, since DOpus surrounds those paths with quotes by default, unless specified otherwise (@nofilenamequoting).

Ideas I've had:

  • What happens if I strip all quotes with @nofilenamequoting, surround the files arg with quotes manually and use " "as a separator (|sep) with "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" "{allfilepath|sep=" "}" @nofilenamequoting or something?
    -> Won't work, I've tried escaping the quotes in various ways, but it looks like sep= really only accepts the first char, not a string
  • Maybe the problem arises from mixed cases and commands without ANY quotes in them would work? (this wouldn't solve the problem but seemed like an interesting question)
    -> No, even CD "C:\Program Files\DAUM\PotPlayer"
    PotPlayerMini64.exe G:\path\withoutspaces.mp4 won't work.

Is there any way for FORCE DOpus to surround all arguments with quotes?
I can hack together a script function, but that seems ugly.

PS: Yes, the particular issue here seems to be a shortcoming of PotPlayer, but after a year or so of trying, their forum still won't verify any of the email accounts I've supplied, so I wasn't able to file a report/request yet :joy:

In the meantime: Here's a command script that creates a command which launches commands surrounding all arguments with quotes:

function OnInit(initData) {
	initData.name = "Call With Quotes";
	initData.desc = initData.name;
	initData.copyright = "(c) 2020 Benjamin Philipp";
	initData.default_enable = true;
	initData.version = "0.1.0";

	// Create a new ScriptCommand object and initialize it to add the command to Opus
	var cmd = initData.AddCommand();
	cmd.name = "CWQ";
	cmd.method = "OnCmd";
	cmd.desc = initData.desc;
	cmd.label = "CWQ";
	cmd.template = "CMD/M";
}

function OnCmd(data){
	DOpus.ClearOutput();
	var args = colToArray(data.func.args.CMD);
	//log(args);
	var cstr = "\"" + args.join("\" \"") + "\"";
	// msg("Result:\n" + cstr);
	data.func.command.RunCommand(cstr);
}


function colToArray(coll){
	var enumFields = new Enumerator(coll); // jshint ignore:line
	enumFields.moveFirst();
	var array = [];
	while (enumFields.atEnd() === false) {
		var i = enumFields.item();
		array.push(i);
		//		log("added: " + i.name);
		enumFields.moveNext();
	}
	return array;
}

function log(obj) {
	DOpus.Output(stringify(obj));
}

function msg(s) {
	var dlg = DOpus.Dlg;
	s = stringify(s);
	log("MSG: " + s);
	dlg.message = s;
	dlg.buttons = "OK";
	dlg.icon = "info";
	var i = dlg.Show();
}

function stringify(obj) {
	if(typeof obj == "undefined")
		obj = "<undefined>";
	else if(obj === null)
		obj = "<null>";
	else if(typeof obj == "object"){
		var o = obj;
		obj = "[Object]\n";
		obj += dump(o);
	} else if(obj === false)
		obj = "FALSE";
	else if(obj === true)
		obj = "TRUE";
	else if(obj==="")
		obj = "<empty>";
	return obj;
}

function dump(arr, level) {
	var dumped_text = "";
	if (!level) level = 0;

	var bs = "\n";

	var level_padding = "	";
	for (var j = 0; j < level + 1; j++) level_padding += "	 ";

	if (typeof (arr) == 'object') { //Array/Hashes/Objects 
		for (var item in arr) {
			var value = arr[item];

			if (typeof (value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "'(" + typeof (value) + "){" + bs;
				dumped_text += dump(value, level + 1) + bs + "}";
			} else {
				if(typeof(value.toString)=="function")
					value = value.toString();
				value = "" + value;
				var m = value.match(/function ?\((.*)\) ?\{/i);
				if(m)
					value = "function(" + m[1] + ")";
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"" + bs;
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>" + arr + "<===(" + typeof (arr) + ")";
	}
	return dumped_text;
}

Usage:
prepend your command with CWQ , for example:
Old: "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" {allfilepath} /sort
->
New: CWQ "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" {allfilepath} /sort

There's no way to force quotes around {allfilepath}, only for the codes that emit a single path/name at a time.

With sep=x, the x can only be one character as well. (That was added for a program that needed * between paths.)

It's unusual for a program to require quotes around paths that don't contain spaces. This seems like a PotPlayer issue to me, more than anything. I'd be surprised if many other programs needed the same thing.

Using scripting is a good workaround for that kind of thing. I would use a simpler script in the button itself (no script add-in):

function OnClick(clickData)
{
	var cmdLine = '"C:\\Program Files\\DAUM\\PotPlayer\\PotPlayerMini64.exe"'

	var selected = clickData.func.sourcetab.selected;
//	if (selected.count == 0) return; -- to block launching the program with no paths

	for (var eSel = new Enumerator(selected); !eSel.atEnd(); eSel.moveNext())
	{
	//	if (eSel.item().is_dir) continue; -- if you want to skip dirs
		cmdLine += ' "';
		cmdLine += eSel.item().RealPath;
		cmdLine += '"';
	}

	var cmd = clickData.func.command;
	cmd.ClearFiles();
	cmd.RunCommand(cmdLine);
//	DOpus.Output(cmdLine); -- for testing
}
1 Like

Yes, I agree :slight_smile:

Even though I might not ever run into this problem again with anything else, I liked the idea of universality and having an add-in ready for this that I could simply prepend to any regular button command.
But of course your neat button script is the more elegant solution to strictly solve the issue once.

Thanks for the feedback, prompt and helpful as ever! :grinning:

1 Like

When filename has quote ' then passed file to powershell will throw exception, because path's here are handles differently if you compare with sending to CMD.

files.ps1 '"I:\Vi\filename'abcdef.ext"'

Any suggestion how to overcome this?
Button code I had, has this section tweaked a bit, but doesn't help at all. Likely I tried to add few more escape symbols.

	//	if (eSel.item().is_dir) continue; -- if you want to skip dirs
		cmdLine += ' \'"';
		cmdLine += eSel.item().RealPath;
		cmdLine += '"\'';
	}

I have dejavu feel, that I had asked this somewhere before.

What's the full command line you're trying to run for each file or batch?

What does your code to build/run that command look like at the moment?

Script log.
powershell D:\_DOCUMENTS\Scripts\source\makefiles.ps1 '"I:\aaa\filewith'symbol.zip"'

And button code, I took from solution post here.

function OnClick(clickData)
{
	var cmdLine = 'powershell D:\\_DOCUMENTS\\Scripts\\source\\makefiles.ps1'

	var selected = clickData.func.sourcetab.selected;
	if (selected.count == 0) return; //-- to block launching the program with no paths

	for (var eSel = new Enumerator(selected); !eSel.atEnd(); eSel.moveNext())
	{
	//	if (eSel.item().is_dir) continue; -- if you want to skip dirs
		cmdLine += ' \'"';
		cmdLine += eSel.item().RealPath;
		cmdLine += '"\'';
	}

	var cmd = clickData.func.command;
	cmd.ClearFiles();
	cmd.RunCommand(cmdLine);
	DOpus.Output(cmdLine); //-- for testing
}

If I grab output and insert into CMD.
Code with files without quotes, will run fine.
If there is quote.

The string is missing the terminator: '.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

I'm even leaning into bulk renaming to make files be without odd symbols.

Presumably you need to escape the ' character in the filename, since that character is also the quote character you're using on the command line.

I'm not familiar with the details of PowerShell to know how that should be done (or if this double-quoting is required at all).

I would get the command working when you type and run it by hand in a command prompt, so you know you're trying to generate the correct thing, then worry about how to generate that in the script (which should be the easy part).

I think you need to escape the quotes with backticks for powershell, i.e.

`"some stuff`"
1 Like

Nice one, actually works, but I don't really thing its feasible to tinker with script. Because there will be another symbols that can break again, like & .

This script adds quotes around passed parameters, and wont insert escapes in middle.
But probably there are topics in forum how to do it. Definitely I'm not the first one.

On other hand, should be pretty much, find symbol & and replace it with `& :slight_smile: