Rename then copy MOVE a file fails because windows still thinks file has old filename

Ah!!
Sorry @Ixp I don't mean for you to be telling me stuff twice.
Below is repeat of test15 above fixed so it is working.

One reason I am slow on the uptake is that I am not understanding what is represented between the curly brackets. So below is an bit of a study and analysis. Any comments/corrections appreciated:

In the case of Test15b above
{alias|Work|regexp}
These seem to be Codes for passing filenames which are a form of External control codes. These, despite the reference to external programs, "may also be used with the internal commands":

In particular, {alias|Work|regexp} are modifiers.

{alias}
{alias} is in fact a Code for passing paths (Makes sense. Here is the explanation from the manual below)
Although it does not specifically say so, it seems that you need 2 entries of the form
{AAA|BBB}
where
AAA = Static keyword "alias"; and
BBB = the actual alias that you want to reference. In my case above the alias is /Work. Note I do not have the forward slash in as part of the modifier. Just the alias work

{work}
This is the actual alias to be referenced as per my explanation above.

{escregexp}
If excluded then this breaks test15b above.
The regex capture group \1 is interpreted as a literal digit 1 unless when this modifier is missing.
It is interesting to me that the modifier is INSIDE the curly brackets and the capture group is OUTSIDE.
My understanding was that the modifier only affects what is inside the curly brackets. Apparently not.
Also if missing then test 14 above does NOT break. Don't know why but I have learned the hard way to stick to instructions from @Ixp :slight_smile:

{escbackslash}
Manual notes below.
This is in fact not part of my working commands but was suggested by @Ixp at one point above.
Note I am in fact using 4 x Backslashes //// in the script string.
Separate analysis to follow

Four Backslashes == 4 x / == ////
Consider my working "ASK" internal command string.
The string a written within the script (I call this the "in script" form) has 4 backslashes see Note 2 below.
Why?
Once the script has run it passes the command to opus in the form shown in Note 1 below. ("out of script" form)
Reg regex capture group syntax calls for the form \n where n is the capture group number.
In my command I have only one capture group so the regex syntax is \1
The TO="...." component of the command has inverted commas (double quotes) around it.
Because of this an additional backslash is required as an escape character to present the second backslash as a literal. Hence double backslash in the "out of script" command form (Note1)
The In script string has additional inverted commas (single quotes). Because of this, for the same reason as above, an additional backslash is needed for each existing backslash.
Hence 4 backslashes in all.

By writing out the above I have improved my understanding of the tools I am using. Hope I can be more self sufficient going forward!!!! Thank you! Gracias! Merci beau coupe! Etc. Etc.!!!!!

A few comments :slight_smile:

:one:

escbackslash vs. escregexp: escbackslash is probably only useful outside renames (though it often will work). For any regex rename, use escregexp.

:two:

the modifier only affects what is inside the curly brackets. Apparently not

Rule: The modifier only affects what is inside the curly brackets!

Look further down for an exception :hushed:

:three:

single vs. double quotes: a pure JScript thing. I like to use single quotes for JScript and reserve the double quotes for Opus commands. Going "all double quotes" is possible, but then you would need even more \ :slight_smile:

:four:

The string a written within the script (I call this the "in script" form) has 4 backslashes see Note 2 below. Why?

The script variant has \\\\ because the normal command has \\. Why? Again, a pure JScript thing: "backslashes need to be escaped (with backslashes)". Period :slight_smile:

So the more interesting question is: Why does the normal variant use \\?

Well, I thought I had a good explanation. Turned out I didn't. At least not in the way I originally envisioned. I now think it's a bug. I've written a separate report.

:five:

General advice: There is nothing wrong with using codes in Rename statements, especially if you want to be able to later/again/also use the statements in normal (non-script) buttons. But if you go all-in with scripting, use the item properties and the JScript regex support. It'll make your code a lot easier to understand/debug/maintain :+1:

2 Likes

I... errrm need more help.

:zero: Thanks
(BTW Thanks @lxp now I can do fancy numbering :one: /:two: /:three: etc. Nice. I love fancy ■■■■ like that :slight_smile: )

:one: Existing working Internal Command (IC)
With thanks to @lxp and others I have the following in the back which works:

rename PATTERN=(.*) TO="{alias|' + Destination_Alias + '|escregexp}\\\\1' + Str_Suffix + '" REGEXP IGNOREEXT

This IC will act on the currently selected files as follows:
:gear: Rename the files by adding the suffix defined in the variable Str_Suffix
:gear: Move the files to the folder defined by the alias contained in the variable Destination_Alias
This is cool.

:two: Objective
To add a subfolder in the Destination_Alias and move the renamed files to that subfolder.

:three: Approach
I find it difficult to present clearly here what changes I have tried and the results I have got.
So rather then causing confusion I thought I would present my analyis of the working command above with a view to understanding it better.
Then I might be better equipped to tackle these things on my own.
I am particularly interested in 2 occurrences of backslashes as follows

:four: Inscript vs OutScript
InScript - This is the IC string that is assembled within the Javascript code.
OutScript - When the JS runs it presents the IC string to Opus to run. The form that is presented changes somewhat from the original InScript form. The OutScript form has to work from a button. It can be tested by executing it via the FAYT prompt.

:five: Regex Capture Group Backslashes
Q1 Is this analysis correct?
This is highlighted in light turqois and number 1 in the screenshot.
InScript - \\\\1 - Four required in order to present 2 backslashes in the OutScript string
OutScript - \\1 - First \ acts as an escape character to signal that the second \ is a literal
Filename - \1 - This represents the single Regex Capture group in our case the entire filename stem.

:six: Folder Delineator Backslash
Q2 Is this analysis correct?
This is highlighted in orange and number 2 in the screenshot.
InScript - - This backslash is not explicitly defined here. I assume that it is provided as part of the "path of the folder alias". (Quoted from the definition of the {alias} external control code. There is a screenshot of this defintion in the post above.)
OutScript - - Not present here for the same reason as above.
Filename - - This is inferred to be present as the IC command works as intended. the fully qualified name (i.e. complete with path) would necessarily have the aforementioned \ in the right place.

:seven: Add a subfolder to the destination
Q3 What would the correct IC form be to do this?
As mentioned above I am not presenting my attempt here as I think it will confuse things.
I have made several attempts actually.
And the results I have got have gien me reason to be interested in the backslash situation above.

With thanks as always

Here's a little something to play with. Needed more backslashes than I anticipated, but apparently also the Rename statement wants more than its fair share of \. Have fun!

function OnClick(clickData) {
    var cmd = clickData.func.command;
    cmd.deselect = false;

    cmd.RunCommand('Set UTILITY=otherlog');

    DOpus.ClearOutput();

    var Destination_Alias = 'work';
    var newFolder = 'I am new here';
    var Str_Suffix = ' suffix';

    var cmdLine = 'Rename PATTERN=(.*) TO="{alias|' + Destination_Alias + '|escregexp|noterm}' + '\\' + newFolder + '\\' + '\\\\1' + Str_Suffix + '"' + ' REGEXP IGNOREEXT';

    DOpus.Output(cmdLine);
    // cmd.RunCommand('dopusrt /argsmsgbox ' + cmdLine);
    cmd.RunCommand(cmdLine);
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="label" hotkey_label="yes" label_pos="right" textcol="none">
	<label>45763 JS</label>
	<tip>rename-then-copy-move-a-file-fails-because-windows-still-thinks-file-has-old-filename</tip>
	<icon1>#script</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    cmd.RunCommand(&apos;Set UTILITY=otherlog&apos;);</instruction>
		<instruction />
		<instruction>    DOpus.ClearOutput();</instruction>
		<instruction />
		<instruction>    var Destination_Alias = &apos;work&apos;;</instruction>
		<instruction>    var newFolder = &apos;I am new here&apos;;</instruction>
		<instruction>    var Str_Suffix = &apos; suffix&apos;;</instruction>
		<instruction />
		<instruction>    var cmdLine = &apos;Rename PATTERN=(.*) TO=&quot;{alias|&apos; + Destination_Alias + &apos;|escregexp|noterm}&apos; + &apos;\\&apos; + newFolder + &apos;\\&apos; + &apos;\\\\1&apos; + Str_Suffix + &apos;&quot;&apos; + &apos; REGEXP IGNOREEXT&apos;;</instruction>
		<instruction />
		<instruction>    DOpus.Output(cmdLine);</instruction>
		<instruction>    // cmd.RunCommand(&apos;dopusrt /argsmsgbox &apos; + cmdLine);</instruction>
		<instruction>    cmd.RunCommand(cmdLine);</instruction>
		<instruction>}</instruction>
	</function>
</button>
1 Like

It works! But you knew that :slight_smile: Thanks...

:one: Regret one more - Call this "Folder-Ask-XX" or "FAxx"
It is with great regret that I approach once more.
The last piece in my scripting jigsaw is to alter the IC command string that @Ixp generated above to achieve the following.
I was determined to manage this one myself but alas...

:two: Variables

var Destination_Alias = 'work';
var newFolder = 'I am new here';
var Str_Suffix = ' suffix';

:three: Internal Command Actions
With the currently selected files

  1. Throw up the Opus {dlgfolder|Your choice!| + Destination_Alias}
  2. Create a subfolder in the selected (destination location defined by variable = newFolder)
  3. Add the suffix to the selected files as defined by variable Str_Suffix = ' suffix';
  4. Move the selected (and prefixed) files to the newly created subfolder

The above amount to exactly what @Ixp nutted out for me in the "have fun" script above with the single exception that the {dlgfolder|Your choice!| + Destination_Alias} is thrown up. No other difference.

:four: Target Internal Command
I believe this is the IC we want to generate from JScript.
The variables are assigned as follows:
Destination_Alias = '/work';
var newFolder = 'SubFolder';
var Str_Suffix = ' 4444'; (Noted first character is a space)

Rename PATTERN=(.*) TO="{dlgfolder|Your choice!|/Work|escregexp|noterm}\SubFolder\\\1 4444" REGEXP IGNOREEXT

:five: My Results
For what they are worth, a selection of my test results which seem to me informative are below.
Once again I have issues with backslashes having, what seems to me, random effects...

Let's end the suffering and do a normal rename, shall we?

function OnClick(clickData) {
    var cmd = clickData.func.command;
    cmd.deselect = false;

    cmd.RunCommand('Set UTILITY=otherlog');

    DOpus.ClearOutput();

    var Destination_Alias = 'work';
    var newFolder = 'I am new here';
    var Str_Suffix = ' suffix';

    var cmdLine = 'Rename PATTERN=* TO="{dlgfolder|Your choice!|/' + Destination_Alias + '|noterm}' + '\\' + newFolder + '\\' + '*' + Str_Suffix + '"' + ' IGNOREEXT';

    DOpus.Output(cmdLine);
    // cmd.RunCommand('dopusrt /argsmsgbox ' + cmdLine);
    cmd.RunCommand(cmdLine);
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" hotkey_label="yes" label_pos="right" textcol="none">
	<label>45763b JS</label>
	<tip>rename-then-copy-move-a-file-fails-because-windows-still-thinks-file-has-old-filename</tip>
	<icon1>#script</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    cmd.RunCommand(&apos;Set UTILITY=otherlog&apos;);</instruction>
		<instruction />
		<instruction>    DOpus.ClearOutput();</instruction>
		<instruction />
		<instruction>    var Destination_Alias = &apos;work&apos;;</instruction>
		<instruction>    var newFolder = &apos;I am new here&apos;;</instruction>
		<instruction>    var Str_Suffix = &apos; suffix&apos;;</instruction>
		<instruction />
		<instruction>    var cmdLine = &apos;Rename PATTERN=* TO=&quot;{dlgfolder|Your choice!|/&apos; + Destination_Alias + &apos;|noterm}&apos; + &apos;\\&apos; + newFolder + &apos;\\&apos; + &apos;*&apos; + Str_Suffix + &apos;&quot;&apos; + &apos; IGNOREEXT&apos;;</instruction>
		<instruction />
		<instruction>    DOpus.Output(cmdLine);</instruction>
		<instruction>    // cmd.RunCommand(&apos;dopusrt /argsmsgbox &apos; + cmdLine);</instruction>
		<instruction>    cmd.RunCommand(cmdLine);</instruction>
		<instruction>}</instruction>
	</function>
</button>
1 Like

@Ixp @Leo and all

:one: Appreciation
First of all I really want to say the help you give is above and beyond.
You really need to have some sort of premium support option for this kind of help.
I would happily sign up.

:two: Folder-Ask-XX or FAXX
I have edited my last request above for which @Ixp has supplied a script (which works of course) to give it a name - Folder-Ask-XX or FAXX. It is the 4th and last IC string I need for my script.

:three: Result
@Ixp's script works. Of course it would. I see you dropped the REGEX as it is not required.
When I incorporate it into my script.....it appears to fail!
This is both

  • Discouraging in that this thing will not die; but on the other hand
  • Encouraging in the sense that I have not obviously been doing anything silly when I tried myself; and I have, believe it or not made a real effort before I appeal for help here. I always do.

:four: Next step - Me troubleshoot my Script
I want to validate what I have seen and make sure I am not making any errors in testing.
Then I will troubleshoot probably by stripping code out my script & progressively testing along the way until either

  • It starts working; OR
  • I strip out enough to make it identical to the working control i.e. Ixp's solution provided above

Hopefully I will solve myself or failing that be able to present any issue in the clearest simplest way possible for anyone to see.

:five: DOpus current version
During most of this blog I have in fact been running Opus 12.21. On 22nd (Friday) I upgraded to the current version as shown below.
There was no change to any of the symptoms/results I was getting at the time.
Directory Opus Pro 12.33 Build 8659 x64
OS 10.0 (B:19045 P:2 T:1) SP 0.0

:six: Windows Update
I see I have a Windows Update ready. I will be installing that and reloading at regular intervals when testing.

Thank you and happy Sunday!

Posting the entire concoction might be the easiest :slight_smile:

been running Opus 12.21

Really? This release is over three years old.

I am starting a new job tomorrow so unfortunately I will not be able to spend much time on this I think.
Pity as I sense momentum and interest is high. Very helpful to me.
I hope I have checked this ok but I have cut down my script and the delta can be seen in the OutofScript presenation in the DOpus.Output of each script. See screenshot below. The InScript string should be identical in both Control(@Ixp) and Broken(@Shaun) scripts. i.e. that which you supplied above (unless I have made an error)

021_051.dcf (15.7 KB)

// Broeken Script ver 021_051 
//
function OnClick(clickData)
{
    DOpus.ClearOutput;
    DOpus.Output("001000 Start 021_051");
    var Str_Suffix = " 4444";
    var FeatureMask = 0xD;
    var cmd = clickData.func.command
	cmd.deselect = false;
        Destination_Alias = "Work"
        DOpus.Output("          040  Str_Suffix                :::"+ Str_Suffix + ":::");
        DOpus.Output("          270  Destination_Alias         :::"+ Destination_Alias + ":::");
        DOpus.Output("          310  FeatureMask               :::"+ ZeroPad((FeatureMask).toString(2),4) + ":::");
            Str_Folder = "NewSubF"
        DOpus.Output("          320  Str_Folder                :::" + Str_Folder + ":::");
        //
        FeatureMask = ZeroPad(FeatureMask.toString(2),4)
        DOpus.Output("   004000-100-000  FeatureMask                   =  " + FeatureMask);
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        Str_Folder = ""
		Str_Command_FAxx_Folder__Ask_13_Ixp   = 'Rename PATTERN=* TO="{dlgfolder|Your choice!|/' + Destination_Alias + '|noterm}' + '\\' + Str_Folder + '\\' + '*' + Str_Suffix + '"' + ' IGNOREEXT';
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        if (FeatureMask.charAt(0) === '1')                           // <-----------------------------------------------------------------------------------------------------
    	{
            DOpus.Output("Hit on Case 1000 FOLDER");
            //
            DOpus.Output("          ...AND 0100 ASK");
            DOpus.Output("          280-100  Case FeatureMask        -A-- =  " + ZeroPad((FeatureMask&0x4).toString(2),4));
            Str_Command_EXEC = Str_Command_FAxx_Folder__Ask_13_Ixp
            DOpus.Output("          280-110  Str_Command_EXEC = Str_Command_FAxx_Folder__Ask_13_Ixp   :" + Str_Command_FAxx_Folder__Ask_13_Ixp);
        }                                                              // <-----------------------------------------------------------------------------------------------------
        DOpus.Output("");
        DOpus.Output("004000-300-100  Str_Command_EXEC   =                                        :" + Str_Command_EXEC);
        CmdResult = cmd.RunCommand(Str_Command_EXEC);
    DOpus.Output("005000 Process Dialog box RETURN END");
    DOpus.Output("");
}

function ZeroPad(s,c)
{
	s = s + "";
	while(s.length < c)
	{
		s = "0" + s;
	}
	return s;
}

Line 15 is

Str_Folder = "NewSubF"

but line 21 is

Str_Folder = ""

So it's no big surprise it's missing in the final command statement.

Or did I misunderstand the problem?

The script is butchered, that's the only logical explanation I can find for what I see.

Oh dear that is embarrassing and also great news.
I would have found it eventaully haha!
I will have a proper look asap but I think you have found my problem. Again.
I wanted to fix this last item before I start work at new job and it is literally 0623h here
Thanks so much!!!!!

So...
With kind help I have 4 rename commands that are components of my script.
One of them, grandly named Str_Command_00xx_NoAsk has an Inscript string as follows:
'rename PATTERN=(.*) TO="{alias|' + Destination_Alias + '|escregexp}\\\\1' + Str_Suffix + '" REGEXP IGNOREEXT'

In some cases Str_Suffix is empty. In such cases the OutScript resolves to the following:
rename PATTERN=(.*) TO="{alias|al20|escregexp}\\1" REGEXP IGNOREEXT
Where
al20 = The alias being referenced

It seems that when the alias resolves to a path that has itself no spaces then it works.
But if there is a space then the filename is changed to "1.png".
Working and control results below are generated from FAYT with the OutScript strings shown.
No script run for these tests.

Any ideas how I might address? With thanks...

Isn't this what we already discussed in Esc* modifiers eat backslashes - #4 by Leo ?

My advise there: Instead of "{alias|xyz|escregexp}\\1"
use "{alias|xyz|noterm|escregexp}\\\\1"

(And maybe add @nofilenamequoting as well, although it seems to be optional.)

Hi @Leo indeed honestly i am not understanding that bug.
I thought the bug applied to parameters outside the {}? Not sure though.
Adding noterm| and \\ as instructed made no difference see below.
Not sure how to use @nofilenamequoting in FAYT. Is that possible?

I'm not sure I follow your diagram.

What's the file path being renamed?

What is the a120 alias defined as?

Have you tried adding @nofilenamequoting?

With going back to a regex rename the old problem (probably a bug) came back: \1 needs an additional \ when it's the first component of the new file name. So your script needs to replace Str_Suffix with \ if it is empty.

@slouw I don't follow you seriously. Does your script do anything more complicated than the screenshots you show or why do you need to use regex there? Or codes like {alias} that are more intended to be used outside of scripts and also have their equivalents. A simplified way to approach your problem would be:

function OnClick(cmdData) {
	DOpus.Output('START!!');
	var dest = cmdData.func.dlg.GetString('Enter alias name', 'al20', 100, 'Ok|Cancel', "Alias Name");
	if (!dest) return;
	var suffix = cmdData.func.dlg.GetString('Enter suffix');
	if (suffix === undefined) suffix = '';
	try {
		dest = DOpus.Aliases(dest).path;
	}
	catch (e) {
		DOpus.Output("You're screwed!!");
		return;
	}
	if (!DOpus.FSUtil.Exists(dest)) {
		DOpus.Output("You're screwed again!!");
		return;
	}
	var cmd = cmdData.func.command;
	var cmdline = 'RENAME IGNOREEXT PATTERN=* TO="' + dest + '\\*' + suffix+'"';
	DOpus.Output(cmdline);
	cmd.RunCommand(cmdline);
	DOpus.Output('DONE!!');
}

Testing with your examples gives me no errors. The example is simplified since you don't show the whole process you are doing or what you need it for. For your example I think COPY MOVE would also work and use AS if you need to add a suffix, but I don't see the need to use regex, at least in your example.

I am working on removing Regex. I know you removed that with one of my 4 rename strings you helped me with. Thanks....