SIMILARBASE but from/to destination display

I have a couple of files selected in the source display and I need to select all the files in the destination folder that have similar names. SIMILARBASE would cover the issue but it only works in the source display. Is there a way (even if it's a script) that could convince SIMILARBASE to fetch the information it operates upon from the other display instead of the current one?

Can be done with a short script:

function OnClick(clickData)
{
	var cmd = clickData.func.command;
	cmd.deselect = false;
	cmd.SetSourceTab(clickData.func.desttab);
	cmd.RunCommand("Select SIMILARBASE");
}
1 Like

Hmm. It doesn't work as expected. But perhaps I misunderstood something again. It seems that I developed a habit of that lately. Let me ask something.

I've found one of your answers to a similar question (also asked by me, what a coincidence) in which you said that:

Opus will work out the basename ... and then select based on that using a wildcard.

What I tried is the following: I have a file 'Clipboard Text.txt' selected in your source display and three other files: Clipboard Text.txt, Clipboard Text.Copy.txt, and Copy.Clipboard Text.txt in your destination display. Triggering the code you provided selects the files Clipboard Text.txt, Clipboard Text.Copy.txt. I assume that the wildcard built from the determined basename is basename* and not *basename or *basename* that I'd need to have Copy.Clipboard Text.txt selected as well.

Is this assumption correct?

Yes, SIMILARBASE would select basename.*

But you can also pass the Select command a wildcard, which the script could build using any patterns/rules you want.

I have just tried out your script, but nothing happened when I run this script.


as my screenshot, I have Selected a file name cat.flac in my left file display which is my source file display also. then click the button. My expectation is would select the 1st and the 3rd file from my right file display which is my destination file display also, because both of the file have the common word cat. but nothing happen

The reason nothing happened was already explained in the two posts before yours. There are no cat.* files on the right hand side, so there's nothing to select.

This gave me an idea and I created a new script-less button, which should work but still does not. It seems that some commands do not work well together with others.

Set DEST=Toggle 
Select NONE
Select *{filedest$}*

If I run those three commands one by one, they do what I need. If I try to run them all at once, sometimes they do not. If there are any files selected in Destination when I press the button, it works, but if there are none, it does not. Check this short video here.

{filedest$} says the command should not run unless there is a file selected in the destination.

Is that evaluated the moment the button is pressed or when the command is run? Because there is a file selected in the destination when that command should be executed.

EDIT: nevermind, I changed the code to this:

@disablenosel 
Set DEST=Toggle 
Select NONE
Select "*{filedest|noext}*"
Set DEST=Toggle

and now it works as expected.

When the button is pressed, normally, although the Select command being on a line before may complicate things, as well as the button changing which sides are source/dest on the first line.

I would use scripting instead for this, as you can be more explicit about what you're doing, and also completely avoid the source/dest switching which will make the file display borders flash. (The same advice will apply to a lot of situations where you want to do something against the grain that acts on the destination instead of the source. Scripting lets you do that directly, while using non-script commands requires kludges.)

As an aside, I'd also recommend having a browse through Formatting tips specific to the Opus forum for how to format commands/code on the forum so your * characters don't turn into italics/bold etc. (I've edited both posts in this thread to fix them.)

2 Likes

Okay, I think I get it. Could you check this, please? It does what I need, I only need feedback if there were any mistakes made.

function OnClick(clickData)
{
	DOpus.ClearOutput();
	var cmd = clickData.func.command;
	var src = clickData.func.sourcetab;
	var dst = clickData.func.desttab;
	var stem;
	var wcard;

	cmd.SetSourceTab(dst);
	cmd.RunCommand("Select NONE");
	for (var eSel = new Enumerator(src.selected); !eSel.atEnd(); eSel.moveNext())
	{
		stem = eSel.item().name_stem;
		wcard = "*" + stem + "*";
		DOpus.Output("name: [" + stem + "], wildcard: [" + wcard + "]");
		cmd.RunCommand("Select \"" + wcard + "\"");
	}
}

Also, thanks for pointing out/correcting my formatting errors.

EDIT: by the way, how do you get the tags (keywords) assigned to a file (Item)? And is it possible to run external commands from a script synchronously?

Only thing I can see that you might want to change is that the filename stem should be passed through Wild.EscapeString so that any wildcard characters like ( and ) in the filename are interpreted as literal characters instead of as part of a wildcard expression.

So add

var wild = DOpus.FSUtil.NewWild();

near the top, then change

wcard = "*" + stem + "*";

to

wcard = "*" + wild.EscapeString(stem) + "*";

See:

They're synchronous by default, but some programs (most UI programs) will detach themselves unless you explicitly ask to wait for them. Adding @sync: before the command is usually enough (same as in a non-script button), but Windows Scripting Host also has its own methods to run things which can wait as well, if needed.

(Aside: Please Ask one question per thread )

1 Like

Thank for the help, @Leo!

That makes sense. The only reason I asked those questions here, because they are related, though that may not be apparent to anyone without the context. But I was trying to solve problems one by one, and I didn't know those questions would become problems until I was able to select the files I needed.

This is the end-result code I put together from the info you provided. Finally, I was able to achieve my goal, so thanks again.

function OnClick(clickData)
{
	// DOpus.ClearOutput();
	var cmd = clickData.func.command;
	var src = clickData.func.sourcetab;
	var dst = clickData.func.desttab;
	var stem;
	var wcard;
	var cmdTxt;
	var wild = DOpus.FSUtil.NewWild();
	var srcIsUnprocessed = false;
	var dstIsUnprocessed = false;
	var dlg = DOpus.Dlg;

	dlg.window = DOpus.Listers(0);
	
	dlg.title = "Remove tag";
	dlg.buttons = "Yes|No";

	cmd.SetSourceTab(dst);
	
	
	for (var eSel = new Enumerator(src.selected); !eSel.atEnd(); eSel.moveNext())
	{
		for (var srcTagEnum = new Enumerator(eSel.item().metadata.tags); !srcTagEnum.atEnd(); srcTagEnum.moveNext())
		{
			srcIsUnprocessed = false;
			if (srcTagEnum.item() == "unprocessed")
			{
				srcIsUnprocessed = true;
				break;
			}
		}
		// DOpus.Output("src is unprocessed: " + srcIsUnprocessed);
		cmd.RunCommand("Select NONE");
		stem = eSel.item().name_stem;
		wcard = "*" + wild.EscapeString(stem) + "*";
		// DOpus.Output("name: [" + stem + "], wildcard: [" + wcard + "]");
		
		cmd.RunCommand("Select \"" + wcard + "\"");
		for (var dSel = new Enumerator(dst.selected); !dSel.atEnd(); dSel.moveNext())
		{
			for (var dstTagEnum = new Enumerator(dSel.item().metadata.tags); !dstTagEnum.atEnd(); dstTagEnum.moveNext())
			{			    
				dstIsUnprocessed = false;
				if (dstTagEnum.item() == "unprocessed")
				{
					dstIsUnprocessed = true;
					break;
				}
				// DOpus.Output("dst is unprocessed: " + dstIsUnprocessed);
			}
			
			cmdTxt = "@sync:bcompare.exe \"" + eSel.item() + "\" \"" + dSel.item() + "\"";
			// DOpus.Output("command text: [" + cmdTxt + "]");
			// DOpus.Output("Labels: " + eSel.item().Labels());
			// cmd.RunCommand(cmdTxt);
			if (dstIsUnprocessed == true)			
			{
				dlg.message = "Remove tag 'unprocessed' from\n\n" + dSel.item() + "\n\n?";
				ret = dlg.Show();
				// DOpus.Output("ret: " + ret);
				if (ret == 1)
				{
					// DOpus.Output("Removing tag: 'unprocessed' from [" + dSel.item() + "]");
					cmdTxt = "SetAttr META tags:-unprocessed FILE \"" + dSel.item() + "\"";
					// DOpus.Output("cmd: [" + cmdTxt + "]");
					cmd.RunCommand(cmdTxt);
				}
			}
		}
		if (srcIsUnprocessed == true)			
		{
			dlg.message = "Remove tag 'unprocessed' from\n\n" + eSel.item() + "\n\n?";
			ret = dlg.Show();
			// DOpus.Output("ret: " + ret);
			if (ret == 1)
			{
				// DOpus.Output("Removing tag: 'unprocessed' from [" + eSel.item() + "]");
				cmdTxt = "SetAttr META tags:-unprocessed FILE \"" + eSel.item() + "\"";
				// DOpus.Output("cmd: [" + cmdTxt + "]");
				cmd.RunCommand(cmdTxt);
			}
		}
	}
}

Still, you're right, I should have disassembled this into multiple questions.

I guess trying to do this with pure non-script commands was a lost cause right from the start...

3 Likes

Looks like the start of a very promising career in scripting :+1:

1 Like

Congratulation! you script was also helpful for me. I have no ability to write this kinds of complex script but I love your script.

1 Like

Well, I had no such ability 4 days ago either. This skill comes by having two things (three, actually):

  1. a dummy with a problem of an ever-increasing complexity (does "I surely am able to add just one more little feature-let" feel familiar?)
  2. a combination of lust for knowledge and a degree of laziness that keeps said dummy on the path of exploration for new solutions instead of accepting that some things are impossible (they only look like)
  3. a League of Extraordinary Gentlemen like @Leo and @lxp, who seem to be always willing to help dummies-in-distress

And if others benefit from it? That's just the bonus :wink:

1 Like

Let's hope it does not come to that. We should not lower the bar so much that would mean me being able to make a career in scripting.

Sometimes I miss the good ol' days when I used to use the built-in file manager in Windows. Everything was plain and simple. You had a problem that was complicated just a little bit over trivial? There was a quick answer (it almost feels like it was a template): "It cannot be done. Now move along, please, there's nothing to see here!". But nowadays? Whenever I ask something, @Leo usually starts his answer with something along the line of "Well, you see, there's this thing called scripting..." :stuck_out_tongue_winking_eye: And I should know already that's the moment I'm on the right path. Long and windy one, it will be, but at least not totally perpendicular to the right one.

2 Likes