RegEx in rename script (remove second extension)

Hi all,

I've started fiddling around with DO again...

Currently I'm working on a JS rename button to remove an additional (!) ".bak" extension that has been slapped on to my files. So I want this:

test1.txt     -> test1.txt
test2.txt.bak -> test2.txt
test3.bak     -> test3.bak

My Button (simplified):

@nodeselect
RENAME PATTERN="*" TO="*" 

@script JScript

function OnGetNewName(getNewNameData)
{
    var item = getNewNameData.item;

    re = new RegExp("^([^.]+)\.([^.]+)\.bak$",'i');
    matches = re.exec(item.name);
    DOpus.Output(item.name + " -> " + matches);

    return true;
}

Surprisingly, the result is this:

test1.txt     -> null
test2.txt.bak -> test2.txt.bak , test2 , txt
test3.bak     -> test3.bak , tes , 3

1 and 2 are ok. But the last one has me stumped; the file would be renamed to tes.3. When I try the RegEx in online testers, everything works as expected.

Can anyone explain and/or provide a solution?
Thanks a lot!
MartO

No need for scripting here. A regex on its own can do this:

Type: Regular Expressions
Old Name: (.+\..+)\.bak$
New Name: \1
(Ignore Extension needs to be off in the UI.)

Or, as a button/command:

Rename REGEXP PATTERN="(.+\..+)\.bak$" TO="\1"
1 Like

Thanks a lot, Leo!

I agree that scripting is not needed for this simple purpose - but this is just a small part of my script.

Obviously your regex is more elegant than mine and I can confirm that it works if used like you suggest. However, in my script it still fails: There's a match for the third file which now gets renamed to "test3" (no extension). What's going on? Isn't that result just wrong? Does the regex engine in the script work differently from the one in the rename dialog or a rename command?

This is one way to do it in JScript:

function OnGetNewName(getNewNameData)
{
    var nameString = String(getNewNameData.item);

    return nameString.replace(/^([^.]+)\.([^.]+)\.bak$/i, "$1.$2");
}

Same thing but making the regexp object explicit:

function OnGetNewName(getNewNameData)
{
    var nameString = String(getNewNameData.item);
    var re = /^([^.]+)\.([^.]+)\.bak$/i;

    return nameString.replace(re, "$1.$2");
}

If you create the regexp object using the syntax you were using, it seems to go wrong:

function OnGetNewName(getNewNameData)
{
    var nameString = String(getNewNameData.item);
    var re = new RegExp("^([^.]+)\.([^.]+)\.bak$","i");

    return nameString.replace(re, "$1.$2");
}

That turns test3.bak into tes.3, like you were seeing with the exec method and matches array. I don't know why that is. It's something JScript is doing, not Opus. Could be something subtle about the difference between using the /.../flags syntax vs new RegExp("...", "flags"), or might even be a bug in JScript.

Solved it! The problem is that the backslash is an escape character not only in regex but also in a string. Of course... So to enter a real "." character in the regex, first you need to escape it so it's "\." and then you need to escape the backslash as well: "\\."
And lo and behold: It works! :smile:

@nodeselect
RENAME PATTERN="*" TO="*" 

@script JScript

function OnGetNewName(getNewNameData)
{
    var item = getNewNameData.item;

    re = new RegExp("^([^.]+)\\.([^.]+)\\.bak$",'i');
    matches = re.exec(item.name);
    DOpus.Output(item.name + " -> " + matches);

    return true;
}

You learn something new -- no, you remember something old every day...:blush: Thanks for your input!

2 Likes

Ah, of course! That's a big advantage of the /.../ syntax in JS since it doesn't require escaping backslashes.