Page 1 of 1

Multi-Item Rename

Posted: 29 Sep 2008 17:42
by jacky
XY offers many possibilities when it comes to renaming, but there's one that isn't there and might on occasion be useful to some, the ability to rename a group of items, without any automatic search/replace or anything like that, but specifying each new names individually (Because the current names don't mean nothing, are too different for one pattern to take care of it all, etc)

So this is what this little script will do : select the items, hit Ctrl+Shift+F2 (or whatever KS you assigned to it ;)) and you'll have the current names listed. Simply edit them as you wish, and press OK to apply. You can also paste in there the names from an external text file, etc

Note that again, a file tmp.ini (in the script's folder) will be used, and removed. So if you already use such a thing and don't want it to be gone, make the necessary adjustments.
Also, you will need to switch recursion checker off or you'll get a lot of warnings...

Code: Select all

"Multi-Item Rename... : MultiItemRename"
	sub (getinfo("CountSelected") == 0) ? "_mirNoSel" : "_mirStart";
"_mirNoSel"
	msg "Nothing selected in the file list.";
"_mirStart"
	// del tmp.ini
	sub _delTmpIni;
	// get current/old names
	$old_names = getinfo("SelectedItemsPathNames", "|");
	// store them
	setkey $old_names, "OldNames", "MultiItemRename", "tmp.ini";
	// prepare for editing: remove path
	regexreplace $old_names, $old_names, "[^|]+\\([^\\])|", "$1";
	// make it multi-line
	replace $old_names, $old_names, "|", <crlf>;
	// ask user for new names
	input $new_names, "Enter the new names for selected items, one name per line", $old_names, m;
	// get last 2 bytes
	substr $check, $new_names, -2;
	// and make sure it ends with a CRLF
	$new_names = $new_names . (($check == <crlf>) ? "" : <crlf>);
	// switch to one-line
	replace $new_names, $new_names, <crlf>, "|";
	// and store new names
	setkey $new_names, "NewNames", "MultiItemRename", "tmp.ini";
	// we only start renaming loop if there is a new name and an old name
	$n = ($new_names == "") ? 0 : 1;
	$n = ($old_names == "") ? 0 : $n;
	sub ($n) ? "_mirLoop" : "_mirDone";
"_mirLoop"
	// get list of old names
	getkey $old_names, "OldNames", "MultiItemRename", "tmp.ini";
	// search for the first item
	strpos $old_pos, $old_names, "|";
	// and "extract" it
	substr $old_name, $old_names, 0, $old_pos;

	// get list of new names
	getkey $new_names, "NewNames", "MultiItemRename", "tmp.ini";
	// search for first item
	strpos $new_pos, $new_names, "|";
	// and "extract" it
	substr $new_name, $new_names, 0, $new_pos;
	
	// remove item from list of old names
	substr $old_names, $old_names, $old_pos + 1;
	// saves new list
	setkey $old_names, "OldNames", "MultiItemRename", "tmp.ini";
	// remove item from list of new names
	substr $new_names, $new_names, $new_pos + 1;
	// saves new list
	setkey $new_names, "NewNames", "MultiItemRename", "tmp.ini";
	
	// remove path from old name
	regexreplace $check, $old_names, "^.+\\(.+)$", "$1";
	// get path of item
	regexreplace $old_path, $old_name, "^(.+)\\.+$", "$1";
	// locate an item with the new name in the items to be renamed next
	strpos $p, "|$check", "|$new_name|";
	// "fixing" script: adds "real" rename at the end of the queue: the temp new name (with prefix) as extra old name, with the real new name as new name
	self $path, path;
	$script_fix = 'getkey $old_names, "OldNames", "MultiItemRename", "'.$path.'\tmp.ini"; getkey $new_names, "NewNames", "MultiItemRename", "'.$path.'\tmp.ini"; setkey $old_names."'.$old_path.'\'.$new_name.'.~mir|", "OldNames", "MultiItemRename", "'.$path.'\tmp.ini"; setkey $new_names."'.$new_name.'|", "NewNames", "MultiItemRename", "'.$path.'\tmp.ini";';
	// if found, execute "fixing script"
	load ($p > -1) ? $script_fix : 'incr $void;',,s;
	// and add prefix for now to avoid collision
	$new_name = ($p > -1) ? "$new_name.~mir" : $new_name;
	
	// get old name only (with path)
	regexreplace $old_name_only, $old_name, "^.+\\(.+)$", "$1";
	// in case no new name was specified, we use the old name
	$new_name = ($new_name == "") ? $old_name_only : $new_name;
	// rename item
	rename b, "$new_name/e",, $old_name;

	// get nb of untouched items so far
	getkey $nb_untouched, "NbUntouched", "MultiItemRename", "tmp.ini";
	// adds 1 if old & new names are the same
	$nb_untouched = 0 + (($new_name == $old_name_only) ? $nb_untouched + 1 : $nb_untouched);
	// saves nb of untouched items
	setkey $nb_untouched, "NbUntouched", "MultiItemRename", "tmp.ini";
	// get nb of renamed items
	getkey $nb_renamed, "NbRenamed", "MultiItemRename", "tmp.ini";
	// adds 1 if old & new names are different AND not a tmp rename (which will be counted later)
	$nb_renamed = 0 + (($new_name == $old_name_only) ? $nb_renamed : (($p > -1) ? $nb_renamed : $nb_renamed + 1));
	// saves nb of renamed items so far
	setkey $nb_renamed, "NbRenamed", "MultiItemRename", "tmp.ini";
	
	// we only continue if there is a new name and an old name
	$n = ($new_names == "") ? 0 : 1;
	$n = ($old_names == "") ? 0 : $n;
	sub ($n) ? "_mirLoop" : "_mirDone";
"_mirDone"
	// get nb of untouched and renamed items
	getkey $nb_untouched, "NbUntouched", "MultiItemRename", "tmp.ini";
	getkey $nb_renamed, "NbRenamed", "MultiItemRename", "tmp.ini";
	// del tmp.ini
	sub _delTmpIni;
	// show usual status message
	status "$nb_renamed ".(($nb_renamed == 1) ? "item" : "items")." renamed, $nb_untouched left untouched";
"_delTmpIni"
	setkey 1, "FileExists", "Ensure", "tmp.ini";
	self $path, path;
	delete 0, 0, "$path\tmp.ini";

Re: Multi-Item Rename

Posted: 30 Sep 2008 09:21
by Muroph
very nice script.
but something went wrong last time i used it.
i'll see if i can reproduce it.

Re: Multi-Item Rename

Posted: 02 Oct 2008 04:31
by lukescammell
So is this my wish come true?
lukescammell wrote:
admin wrote:What I could offer: 2 "Misc" new functions in CKS: "Rename Next" and "Rename Previous".

Or, what I have on my mind since long: a rename interface that's a multi-line editbox. So you just move the caret around in a list of names as in a normal text editor, and when done you press OK. You could also copy/paste lists of file names and map them onto the selected files...
Dude, LOVE that idea 2nd idea, although the 1st one would be a good plan too, since then spamalam can do exactly what he wants (and others?) :D

Here's a litle mockup with a couple of suggestions :) The button for changing the text from LTR to RTL and the box selection ability work hand in hand as they can really help with mass editing file extensions (yes I know this only works with 3 letter extensions, but that covers most no? ;))

Image Image Image Image Image

Perhaps CTRL+SHIFT+F2 could activate this editor?

Re: Multi-Item Rename

Posted: 02 Oct 2008 09:15
by Muroph
i give up.
i tried many times, but couldn't reproduce the problem. :?
maybe it was just some really bad luck, wich is quite normal for me. :(

Re: Multi-Item Rename

Posted: 02 Oct 2008 11:43
by lukescammell
Muroph wrote:i give up.
i tried many times, but couldn't reproduce the problem. :?
maybe it was just some really bad luck, wich is quite normal for me. :(
On the one hand, it sucks that you had a problem, but on the other, thanks for making me LOL. I didn't laugh to be mean, it just seemed like such a resigned tone you wrote with :D

Re: Multi-Item Rename

Posted: 02 Oct 2008 20:01
by Muroph
lukescammell wrote:
Muroph wrote:i give up.
i tried many times, but couldn't reproduce the problem. :?
maybe it was just some really bad luck, wich is quite normal for me. :(
On the one hand, it sucks that you had a problem, but on the other, thanks for making me LOL. I didn't laugh to be mean, it just seemed like such a resigned tone you wrote with :D
don't worry.
even my friends laugh when i say i'm unlucky.
it's already a joke in our group. :)
but lately Murphy's ghost is hauting me more than usual.
damn him. :x

Re: Multi-Item Rename

Posted: 28 Nov 2008 17:52
by lukescammell
I jsut remembered this script and gave it a go, unfortunately I can't get it to work. Has anyone managed sucessfully?

Re: Multi-Item Rename

Posted: 28 Nov 2008 18:07
by Muroph
lukescammell wrote:I jsut remembered this script and gave it a go, unfortunately I can't get it to work. Has anyone managed sucessfully?
yup, working here (xy 7.80.0028).
and i must say this is a really useful script. :D

Re: Multi-Item Rename

Posted: 28 Nov 2008 21:11
by Stefan
Yes, this script is very useful :D thanks for sharing.

FYI, i have used and test here the new option setting "allowrecursion", 1;
introduced with XYplorer BETA version (v7.80.0028, 27-nov-2008)

Code: Select all

    + Scripting commands enhanced:
      - setting, settingp
        New named argument "allowrecursion"
          0 = show warning on recursions
          1 = simply go on and hope that the script writer knows what
              he's doing
        Example:
          ::setting "allowrecursion", 1;
        Note: This command is just using a simpler name for the already
        existing INI tweak "ScriptRecursionWarningOff".

as
[...]
"_mirLoop"
setting "allowrecursion", 1;
// get list of old names
[...]
Works all prima, thanks jacky and Don.

Re: Multi-Item Rename

Posted: 24 Jun 2009 17:02
by Mesh
I just tried this script, but ran into a limitation. It won't work for more than 256 files (I was trying to rename about 9000).

To clarify, I got a stack error, XY crashed, and my home directory was deleted. I have to admit, I didn't expect that last one.

Re: Multi-Item Rename

Posted: 24 Jun 2009 17:28
by Muroph
Mesh wrote:I just tried this script, but ran into a limitation. It won't work for more than 256 files (I was trying to rename about 9000).

To clarify, I got a stack error, XY crashed, and my home directory was deleted. I have to admit, I didn't expect that last one.
i've been using this for a while. :D

Code: Select all

"Multi-Rename Mod"
	$total=getinfo("countselected");
	end ($total<1), "Nothing selected";
	$oldlist=report("{name}<crlf>",1);
	$pathlist=report("{fullpath}<crlf>",1);
	$newlist=input("Enter new names",,$oldlist,m);
	$counter=1;
	$renamed=0;
	$untouched=0;
	while($counter<=$total){
		$oldname=gettoken($oldlist,$counter,<crlf>);
		$newname=gettoken($newlist,$counter,<crlf>);
		if("$oldname"!="$newname"){
			$path=gettoken($pathlist,$counter,<crlf>);
			rename ,"$newname/e",,"$path\$oldname";
			$renamed++;}
		else{$untouched++;}
		$counter++;}
	status "$renamed ".($renamed>1)?("items"):("item")." renamed, $untouched left untouched",78ff00,ready

Re: Multi-Item Rename

Posted: 24 Jun 2009 17:53
by Mesh
Muroph wrote:
i've been using this for a while. :D

That did the trick quite nicely! It also came up with the input box much faster as well.

I'm amazed that your script is so much shorter than the original one listed here.


Obviously, the number of files that can be renamed as well as the script's brevity are some advantages your script has over Jacky's. But what about the other way around? Are there benefits to Jacky's script over this one?

Re: Multi-Item Rename

Posted: 24 Jun 2009 18:16
by TheQwerty
Mesh wrote:I'm amazed that your script is so much shorter than the original one listed here.

Obviously, the number of files that can be renamed as well as the script's brevity are some advantages your script has over Jacky's. But what about the other way around? Are there benefits to Jacky's script over this one?
I can't speak for the actual script content, but a lot of jacky's script was to get around the limitations of XY's scripting language.

I believe jacky wrote that script before Don had blessed us with global variables and certainly before the while loop, so jacky had to do everything using multiple sub-scripts with recursion and had to read/write values to INI files (or the script file itself) to communicate data between the sub-scripts.

The biggest advantage is that jacky's version will work on much older versions of XY.

It's really a testament to how much Don has improved scripting in the time since it was introduced.

EDIT: And also jacky's was before we had "if" so that would require branching to a sub-script anytime the action would change due to some logical expression.