Swap the names of two files

This rename script (in the form of a toolbar button) will exchange (swap) the names of each pair of selected files or folders.

:arrow_right: See the Button .dcf Files under How to use buttons and scripts from this forum for how to add .dcf files to your toolbars.

New version:

This is an updated version for Opus 12 which does things in a cleaner way, and with support for logging what was done.

:warning: Undo doesn't currently work (also an issue with the old version). For now, the best way to undo a swap is to simply run it again and swap things back.

Two versions are provided:

Script code for reference:

This code is contained in the .dcf files above. It's only reproduced here so you can see how it works without downloading anything.

Click either section to expand it.

Preserve extensions
function OnClick(clickData)
{
	var sourceTab = clickData.func.sourcetab;

	// Go through the selected items in pairs.
	var eSel = new Enumerator(clickData.func.sourcetab.selected);
	while (!eSel.atEnd())
	{
		var fileA = eSel.item();
		eSel.moveNext();

		if (eSel.atEnd())
			break; // Odd number of files selected.

		var fileB = eSel.item();
		eSel.moveNext();

		SwapFiles(sourceTab, fileA, fileB);
	}
}

function SwapFiles(sourceTab, fileA, fileB)
{
	// Swap two files' names, preserving each file's extension.

	var cmd = DOpus.Create.Command();
	cmd.SetSourceTab(sourceTab);
	cmd.deselect = false;

	var nameA = fileA.name_stem_m;
	var nameB = fileB.name_stem_m;

	cmd.AddLine("Rename PATTERN * TO *");
	cmd.AddLine("@script jscript");
	// Heard you liked scripts, so we put a script inside your script.
	cmd.AddLine('function OnGetNewName(data) {');
	cmd.AddLine('	if (data.newname_stem_m == "' + nameA + '")');
	cmd.AddLine('		return "' + nameB + '" + data.newname_ext_m;');
	cmd.AddLine('	if (data.newname_stem_m == "' + nameB + '")');
	cmd.AddLine('		return "' + nameA + '" + data.newname_ext_m;');
	cmd.AddLine('}');

	cmd.AddFile(fileA);
	cmd.AddFile(fileB);

	cmd.Run();
}
Swap whole names
function OnClick(clickData)
{
	var sourceTab = clickData.func.sourcetab;

	// Go through the selected items in pairs.
	var eSel = new Enumerator(clickData.func.sourcetab.selected);
	while (!eSel.atEnd())
	{
		var fileA = eSel.item();
		eSel.moveNext();

		if (eSel.atEnd())
			break; // Odd number of files selected.

		var fileB = eSel.item();
		eSel.moveNext();

		SwapFiles(sourceTab, fileA, fileB);
	}
}

function SwapFiles(sourceTab, fileA, fileB)
{
	// Swap two files' names, including each file's extension.

	var cmd = DOpus.Create.Command();
	cmd.SetSourceTab(sourceTab);
	cmd.deselect = false;

	var nameA = fileA.name;
	var nameB = fileB.name;

	cmd.AddLine("Rename PATTERN * TO *");
	cmd.AddLine("@script jscript");
	// Heard you liked scripts, so we put a script inside your script.
	cmd.AddLine('function OnGetNewName(data) {');
	cmd.AddLine('	if (data.newname == "' + nameA + '")');
	cmd.AddLine('		return "' + nameB + '";');
	cmd.AddLine('	if (data.newname == "' + nameB + '")');
	cmd.AddLine('		return "' + nameA + '";');
	cmd.AddLine('}');

	cmd.AddFile(fileA);
	cmd.AddFile(fileB);

	cmd.Run();
}

Old version:

This was about the only way to do the same thing before Opus 12. The newer methods above are better unless you're on an old version.

This version will swap the whole names, including extensions.

Because rename scripts only run one file at a time, it works by remembering the name of the first file of every pair, and then doing the actual rename when processing the second file of every pair. The rename itself is implemented as a three-step process: 1) first file to temporary name, 2) second file to first file name, 3) temporary name to second file name.

There's no error checking (although it could be added) and because the script uses the FileSystemObject to do the actual rename, rather than Opus itself, there's no way to undo the rename (other than running it again to swap the names back again).

Swap Names (OLD VERSION).dcf (2.7 KB)

Code for old version
Rename PATTERN * TO *
@script vbscript

Option Explicit

Dim strPrevName, strTempName
Randomize()

Function Rename_GetNewName ( strFileName, strFilePath, _
      fIsFolder, strOldName, ByRef strNewName )

   ' for the first file of every pair, save the old file and then rename with a random suffix
   if Len(strPrevName) = 0 Then
      strPrevName = strFileName
      strTempName = strNewName & "-temp" & Int(10000 * rnd())
   else
      Dim oldPath, newPath
      Dim fs
      Set fs = CreateObject("Scripting.FileSystemObject")

      ' rename the first file to a temporary name
      oldPath = fs.BuildPath(strFilePath, strPrevName)
      newPath = fs.BuildPath(strFilePath, strTempName)
      fs.MoveFile oldPath, newPath

      ' rename the second file to the first file's name
      oldPath = fs.BuildPath(strFilePath, strFileName)
      newPath = fs.BuildPath(strFilePath, strPrevName)
      fs.MoveFile oldPath, newPath

      ' rename the first file to the second file's name
      oldPath = fs.BuildPath(strFilePath, strTempName)
      newPath = fs.BuildPath(strFilePath, strFileName)
      fs.MoveFile oldPath, newPath
      
      Set fs = Nothing
      strPrevName = "" ' reset for next file
   end if
   strNewName = strFileName ' nop - rename is handled by the FileSystemObject
      
End Function
5 Likes

Thanks, handy enough so i've adopted the button making my original 2-way button a 3-way button. The button works fine for 2 files in the same lister (i.e. both in source lister!) but not across a dual lister. For 1 file selected the button does nothing, and for 3 (or more) files selected the button does some miracle (instead of doing nothing). i do notice a time lag (delay). maybe i can compress the long script code (or the button itself :wink:) with winrar..

Thanks again jon!!

This script seems to only work if the two selected files have the same extension. If they don't share a file extension, then it fails.

It would be really nice to have this :innocent:

It seems to work fine. What do you mean by "fails"? Nothing happens? Or do you mean it swaps the full names, including the extensions, and you want it to preserve each file's extension?

Leo pardon me for not getting back to you sooner. I have not logged in for some days

On my first try a week ago, nothing seemed to be happening.
After reading your comment. I gave it another try and nothing seemed to happen. I tried changing the file extensions around after running the button on two files and it works as intended.
the names were successfully swapped and so are the files extensions.

Yes this would be ideal!

I've updated the first post with new versions that do things in a cleaner way (which wasn't possible before Opus 12), and where you can choose whether to swap or preserve file extensions.

1 Like

Heard you liked Rename Presets.

Swap Names.orp (822 Bytes)

var tab = DOpus.listers.lastactive.activetab;
var i = 0;
var k = tab.selected.count;

function OnGetCustomFields(getFieldData) {
    getFieldData.fields.swapExtension = true;
    getFieldData.field_labels('swapExtension') = 'Swap extension';
}

function OnGetNewName(getNewNameData) {
    var swapExtension = getNewNameData.custom.swapExtension;
    var j = (i % 2) == 0 ? i + 1 : i - 1;
    var tmp = j < k ? tab.selected(j).name_stem + tab.selected(swapExtension ? j : i).ext : false;
    i++;
    return tmp;
}

How to use Rename Presets from this forum

2 Likes

Just be careful not to activate any other lister or tab while the rename dialog is open. :slight_smile:

2 Likes

Excellent. I will give both of these a try soon as I can. Thank you guys