After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 306489 - rename multiple files at once
rename multiple files at once
Status: RESOLVED FIXED
Product: nautilus
Classification: Core
Component: File and Folder Operations
2.11.x
Other All
: Normal enhancement
: ---
Assigned To: Nautilus Maintainers
Nautilus Maintainers
: 334138 347187 354080 379302 431831 563223 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2005-06-04 17:48 UTC by Alan Horkan
Modified: 2010-11-01 16:29 UTC
See Also:
GNOME target: ---
GNOME version: 2.9/2.10


Attachments
Proposed patch (against HEAD). (18.49 KB, patch)
2005-06-05 12:17 UTC, Christian Neumair
reviewed Details | Review
Possible design for Rename dialog (1.19 KB, text/plain)
2006-07-17 13:00 UTC, Matthew Paul Thomas (mpt)
  Details
Add possibility to register an external bulk rename tool (8.45 KB, patch)
2010-10-05 20:09 UTC, Holger Berndt
needs-work Details | Review
Add possibility to register an external bulk rename tool (6.96 KB, patch)
2010-10-16 21:09 UTC, Holger Berndt
needs-work Details | Review
Add possibility to register an external bulk rename tool (6.56 KB, patch)
2010-10-31 16:23 UTC, Holger Berndt
committed Details | Review

Description Alan Horkan 2005-06-04 17:48:54 UTC
premise: renaming is an integral part of file management and normal users need a
way to rename multiple files at once without being forced to use the command line.  
(see also http://udu.wiki.ubuntu.com/CommandLineDisintegration )

there are various ways this could be implemented and it is up to the developer
to decide but please do decide on something rather than nothing.  The file
explorer in Windows XP provides a fairly straighforward (if slightly inflexible)
system, which is described in this article
http://graphicssoft.about.com/cs/renamers/ht/renamexp.htm

I have also taken a series of screenshots in an attempt to better illustrate the
process
http://www.maths.tcd.ie/~horkana/batch-rename/

Essentially when users have more than one file selected they are prompted to
rename the first file and the other files are renamed to match the same pattern
(although the labelling and rudimentary pattern matching could stand to be
massively improved).  The operation is entirely undoable.
Comment 1 Christian Neumair 2005-06-04 20:12:11 UTC
This sounds like an excellent idea!
Maybe you could try out how it is figured out which file receives a particular
number? Is the alphabetical order decisive or the sorting order? How does it
work with manual layout in icon views? The first item always seems to be the
"master" (i.e. the one not receiving a number in parenthesis).
Comment 2 Christian Neumair 2005-06-04 20:13:20 UTC
Slight addition: My idea would be to just assume alphabetical order for manual
layout.
Comment 3 Alan Horkan 2005-06-04 22:07:58 UTC
> This sounds like an excellent idea!

I'm sorry I didn't file it years ago.  Proves that if I dont bother to file
requests for these things no one else will.  

I'll give you some samples, the first item in each set will be exactly what the
user would have to type

file1.ext
file1 (2).ext
file1 (3).ext
file1 (4).ext
file1 (5).ext

number 01.ext
number 01 (2).ext
number 01 (3).ext
number 01 (4).ext
number 01 (5).ext

nametest (10).ext
nametest (11).ext
nametest (12).ext
nametest (13).ext

Unless you start with a filename using exactly the number format (N) it will be
ignored and the following files will have (2) ... (N) appended to them.  
If you do use exactly the format they require then the list will go from the
where you specify.  


The system they use is pretty simplistic/stupid, and hopefully someone who
implemented this for Nautilus could be a lot smarter about the pattern matching
(possibly borrow some algorithms from Gnumeric for predicting the next items in
the sequence).  
Developers keep having to remind me "the perfect is the enemy of the good" when
I get carried away with details but i think it is far more important to have
something, anything that gets the job done than waiting for a better solution
and i fully support whoever is willing to implement any kind of batch renaming
functionality.  FYI Gthumb has a batch rename tool, which could potentially be
reused as an alternative possibly easier to implement solution.  


If you want more information or alternative suggestions let me know and I'll log
into a windows XP machine and suffer the Microsoft crapfest long enough to get
the information you need.  
Comment 4 Christian Neumair 2005-06-05 12:17:41 UTC
Created attachment 47265 [details] [review]
Proposed patch (against HEAD).

This is a very first show at this issue, so I'm not entirely sure about the
architecture. Also the code quality may be a bit poor.
The idea would be that the first item in the selection is also the first icon
to be renamed and renaming always involves the whole selection. Turns out that
the list view (probably GtkListView's fault) unselects all rows except the one
being renamed, so this currently only works for the icon view.
I'd appreciate if you could apply this patch and give some feedback. If the
first item is a directory, we currently use the directory name and append "
(i)" for the subsequent items. But if the first item is not a directory, we
construct the filename of the subsequent items as "basename (i).extension".
Both patterns are always applied to subsequent items, no matter whether it is a
directory or file. We could be way more smart here. Another bug I've noticed is
that the order of selected files does not depend on the currently active sort
order, which may in some cases make the "rename master" just one of its dups
and make one of the "rename slaves" turn into "bastename" or
"basename.extension" (the "master's" filename).
Comment 5 Alan Horkan 2005-06-14 22:49:09 UTC
I'm hoping to test the patch real soon now and it is gradually creaping up my
priority list.  I promise to get to it before the end of the week.  
Comment 6 Christian Neumair 2005-07-10 15:08:48 UTC
Any news on your priority list? :) Now that we have fixed the selection order,
this should even be useful.
Comment 7 Maciej Katafiasz 2005-07-17 22:57:21 UTC
Note that this should be rather handled by specialised app, just well integrated
with Nautilus. I happen to have written one :), although it's still unfinished.
Right now, the latest released version (0.5) is not suitable for everyday use
(it's known to destroy data under many circumstances), and 0.8, which will have
that fixed is still not out yet. To be developed remain (of the things that
matter for Nautilus) 1) Proper nautilus extension (it's simply a script right
now) 2) Way for ordinary user to easily build name templates, the syntax used is
fairly straightforward, but could still look cryptic for someone not accustomed.

If you want, check it out at http://mathrick.org/software/purrr.html (0.5) and
http://mathrick.org/software/0.8/purrr.html (0.8 prerelease)

Oh, and with selection order fixed, it'll be much more useful, before you needed
to always manually force -1 as counter step to overcome reversed direction.
Comment 8 TuringTest 2005-08-05 10:45:24 UTC
FYI there exists a "perfect" solution for batch renaming. It's an Artificial 
Intelligence technique called Programming By Example (PBE). This article shows a 
simple learning algorithm for watching how the user edits the first rename, and 
then generalizing it to repeat the renaming on all the other files:


Learning Repetitive Text-editing Procedures with SMARTedit
http://web.media.mit.edu/~lieber/Your-Wish/11-Lau.pdf


This visual representation of regular expressions is also relevant - it would be 
much better than text "templates" for creating the new names:
 
SWYN: A Visual Representation for Regular Expressions
http://web.media.mit.edu/~lieber/Your-Wish/13-Blackwell.pdf

Those articles belong to a PBE book called "Your wish is my command". The whole 
book contents are published online:
http://web.media.mit.edu/~lieber/Your-Wish/#ToC
Comment 9 Christian Neumair 2006-03-04 21:23:09 UTC
TuringTest: Thanks for the links, I browsed the documents you pointed out, but in this context I couldn't see any practical link to SMARTedit.

An algorithm for pattern detection might indeed be desirable, for instance we could recognize a string composed of a distinct sequence of numbers and other text, like "foo01bar", decompose it and increment the "01" for the other candidates, i.e. an arbitrary set of selected files would be renamed according to the first example.
Comment 10 Christian Neumair 2006-03-10 21:59:00 UTC
*** Bug 334138 has been marked as a duplicate of this bug. ***
Comment 11 Sergej Kotliar 2006-07-11 11:24:27 UTC
*** Bug 347187 has been marked as a duplicate of this bug. ***
Comment 12 Matthew Paul Thomas (mpt) 2006-07-17 13:00:51 UTC
Created attachment 69039 [details]
Possible design for Rename dialog

The argument that this should be done by an external program would make more sense if Nautilus didn't already have a "Rename…" menu item. Since it does, making that menu item available when multiple items are selected isn't making Nautilus's interface more complex, it's making it more consistent.

This is an updated version of a design I came up with a while ago for a Rename dialog.
Comment 13 apf 2006-07-18 05:39:55 UTC
Matthew, that is a great start.  Does it allow for numbering in a certain format, however?

Suppose I had files with a variety of names, such as eiffeltower.jpg, louvre.jpg and notredame.jpg and so on and I wished to rename these in them format triptoparis00001.jpg, triptoparis00002.jpg and triptoparis00003.jpg

Does it allow renumbering and incrementing at the smae time?  Irfanview would do this by allowing you to set it in the format:

triptoparisnnnnn whereby the "nnnnn" is the number of digits wanted.  IT would then increment by one each time.  I was a little unclear as to whether your design allowed this facility.


Thanks and keep up the great work, my fellow GNOME community members, 

David L S
Hobart, TASMANIA
Comment 14 Sergej Kotliar 2006-09-03 13:59:08 UTC
*** Bug 354080 has been marked as a duplicate of this bug. ***
Comment 15 Joachim Noreiko 2006-12-26 13:02:57 UTC
*** Bug 379302 has been marked as a duplicate of this bug. ***
Comment 16 Cosimo Cecchi 2007-12-31 10:30:06 UTC
*** Bug 431831 has been marked as a duplicate of this bug. ***
Comment 17 Cosimo Cecchi 2007-12-31 10:30:30 UTC
From duplicate bug #431831:

"When using single-click policy it's quite difficult to get one file selected to
have it renamed when trying to do that on a number of files in one folder - you
have to click outside of any file icon (which is hard when having a lot of
files in one folder) or ctrl+click to deselect the previous file.
This one is related to bug 306489, but I'd like the solution to be
user-configured - if one wants to use multi-file rename - ok, but I'd like it
to behave like this - when clicking F2 with multiple files selected, only the
last one selected gets renamed. That should be fairly easy to implement."
Comment 18 Alexander Larsson 2008-10-03 18:48:19 UTC
I once had an idea about another way to handle multiple file rename (at least some of it). If you select a number of files and bring up the property dialog we'd try to determine the parts of the filenames that are the same, and then have the name entry contain uneditable XXX characters for the non-common parts, and only allow you to edit the common parts.
Comment 19 Luca Ferretti 2008-10-04 13:30:53 UTC
Just for reference, here[1] is an utility for MacOS, NameChanger. It should be an "external" utility, i.e. not integrated in Finder.

It provides a simple mode and advanced mode. Take a look to the demo video too, showing the ability to change the intial order using an icon (pre)view.

About Nautilus, I think the optimal solution could be provide an external well beaving, full featured tool in GNOME Desktop and let it integrate in Nautilus, instead try to fix this directly in Nautilus. I don't think we want to include in Nautilus code something like NameChanger, but also users will love - no need, love :) - to have an ultra-mega-special tool like this. And they'll complain about the missing advanced feautures.

I think the best could be something like the Archive <-> File Roller approach: if you want create a new archive, you can select files in Nautilus and choose "Create Archive...": this will bring you a small dialog with limited options (name, type, location). But you can also directly open File Roller and add files and folders from differente locations to a new empty archive, changing their names or adding directories too. 

Of course could be really good if we can always use the existing "Rename.." menu item.

So, summarizing, Nautilus + NYNACF[2] should:
 * 1 file selected + Rename --> current Nautilus behavior
 * N files selected + Rename --> invoke NYNACF in simple mode
               (something like apply the same template to all files)
 * NYNACF + d'n'd --> all advanced renaming options that users love to have

[1] http://web.mac.com/mickeyroberson/MRR_Software/NameChanger.html
[2] == No Yet Name Application to Change Filenames
Comment 20 Cosimo Cecchi 2010-05-02 14:44:00 UTC
*** Bug 563223 has been marked as a duplicate of this bug. ***
Comment 21 Holger Berndt 2010-09-24 09:26:51 UTC
I fully agree to #19, that an approach similar to File Roller or Seahorse would be great. I wonder how Nautilus would start that external application. This is different to extensions like Seahorse or File Roller, in that the external application doesn't add menu entries or the like, but is supposed to be triggered on Nautilus very own "Rename" action in the case of multiple files being selected. That has some implications, for example that by design at most one such tool can be registered at any given time.

I propose the following integration, which roughly resembles "preferred applications" desktop settings:

Nautilus could add a string-valued GSettings key like "bulk-rename-application". When not empty, the Rename action stays sensitive even when multiple files are selected. On activation, Nautilus would execute "$KEY_VALUE URI1 URI2 [URI3 URI4 ...]".

Bulk rename applications could register themselves with Nautilus during their installation or first start by setting that key. Nautilus could maybe clear that key on failed invokation attempts.

I may have a look at creating a patch for that if the proposal is acceptable.
Comment 22 Holger Berndt 2010-10-05 20:09:22 UTC
Created attachment 171786 [details] [review]
Add possibility to register an external bulk rename tool

If the new setting "bulk-rename-tool" in org.gnome.nautilus.preferences
is set to a non-empty string, it is treated as a bulk renamer and
gets invoked on a Rename action if multiple files are selected.
Nautilus appends a space separated list of URIs of all selected
files to the command string.
Comment 23 Cosimo Cecchi 2010-10-13 17:37:19 UTC
Review of attachment 171786 [details] [review]:

Hi Holger, I quite like having this working with external applications targeting power-users. Could you link me to one you think is nice to use so that I can try it? (or are you developing one application of this kind yourself? :))

The approach seems fine, I inlined some comments about the code below.

::: src/file-manager/fm-directory-view.c
@@ +1888,3 @@
+
+static void
+update_rename_button_sensitivity_bulk_rename_changed (GSettings *settings, gchar *key, FMDirectoryView *view)

There's no need to update the actions here, as you would update them anyway next time real_update_menus() is called (i.e. when the selection changes, which is what we care about); see below for a longer explanation.
If you remove this callback, the prototype for _can_rename_file() you added at the beginning of the file would go away.

@@ +6141,3 @@
+		quoted_parameter = g_shell_quote (parameter);
+		g_free (parameter);
+		tmp = g_strconcat (full_cmd, " ", quoted_parameter, NULL);

It's probably easier to use a GString for this kind of operations.

@@ +8570,3 @@
+			g_signal_connect (nautilus_preferences,
+					  "changed::" NAUTILUS_PREFERENCES_BULK_RENAME_TOOL,
+					  G_CALLBACK (bulk_rename_tool_setting_changed_callback), NULL);

AFAICS this will connect a signal handler every time real_update_menus() is called, which is wrong.

I think what I would do is:
- don't connect to any 'changed' signal coming from GSettings
- in have_bulk_rename_tool(), update your local stripped copy of the GSettings string
- in real_update_menus(), do basically what you do now, except for the if (block_rename_tool == NULL) {} block, which would go away.

You could also connect to the 'changed' signal in _init_view_iface() as you do now, instead of fetching the string from the settings at every menu refresh, but you would just update the stripped string copy there.
Comment 24 Holger Berndt 2010-10-16 21:09:29 UTC
Created attachment 172512 [details] [review]
Add possibility to register an external bulk rename tool

If the new setting "bulk-rename-tool" in org.gnome.nautilus.preferences
is set to a non-empty string, it is treated as a bulk renamer and
gets invoked on a Rename action if multiple files are selected.
Nautilus appends a space separated list of URIs of all selected
files to the command string.
Comment 25 Holger Berndt 2010-10-16 21:13:23 UTC
Thanks a lot for reviewing, Cosimo!

> Could you link me to one you think is nice to use so
> that I can try it?

Any bulk renamer that can handle URIs on the command line should work fine
(e.g. "thunar -B" for local URIs).

> (or are you developing one application of this kind
> yourself? :))

Actually, I am (though it is a Python app, and currently a bit stalled on
gobject introspection porting).

Basically, it's supposed to work like Luca wrote in #19. The idea is that 
the simple mode defaults to what Alex describes in #18 and changes
common name substring if there is one, and offers some simple common
options if that's not the case ("Replace spaces with underscores" kind of
stuff) - plus a "Show me the full thing" button that opens the
bulk renamer in normal mode.

> There's no need to update the actions here, as you would update them anyway
> next time real_update_menus() is called (i.e. when the selection changes, which
> is what we care about); see below for a longer explanation.

Actually, I was aware of that. The callback was supposed to update the action
sensitivity of the current selection when the GSettings key changes. But you're
probably right that this is a bit of an overkill. I removed it from the updated
patch.

> It's probably easier to use a GString for this kind of operations.

Updated.

> AFAICS this will connect a signal handler every time real_update_menus() is
> called, which is wrong.

No, only the very first time. The bulk_rename_tool variable is global and shared
among all views, and is only NULL at the very beginning. On consecutive calls, 
if no bulk rename tool is registered, it will be "".

Just in case if there is some reason why g_settings_get_string() might
return NULL that I am not aware of, I added a safety net in
bulk_rename_tool_setting_changed_callback(). Otherwise, I left it as it
was (except more elaborate comments). Please don't hesitate to throw this one back to me if I still didn't get it :-)

> I think what I would do is:
> - don't connect to any 'changed' signal coming from GSettings
> - in have_bulk_rename_tool(), update your local stripped copy of the GSettings
>   string
> - in real_update_menus(), do basically what you do now, except for the if
>   (block_rename_tool == NULL) {} block, which would go away.

Hm, I was thinking about that too, but changing the selection is a very common
operation. I understand that GSettings is optimized for reading, but I was
hesitant if it's really a good idea to read that rather exotic key with high
frequency - especially when it's not really necessary.
Comment 26 Cosimo Cecchi 2010-10-20 12:42:48 UTC
Review of attachment 172512 [details] [review]:

Some other comments on the code.

::: libnautilus-private/org.gnome.nautilus.gschema.xml.in
@@ +241,3 @@
       <_description>If set to true, then hidden files are shown by default in the file manager.  Hidden files are either dotfiles, listed in the folder's .hidden file or backup files ending with a tilde (~).</_description>
     </key>
+    <key name="bulk-rename-tool" type="s">

I think you should make it clearer whether this should be a full path to an executable file or the name of one in $PATH. It could also be safe to allow both, but this should be made clearer in the description.

Note that in both cases, I think the setting should become an array of bytes ('ay' signature), as we are storing a filename, not an UTF-8 string.

::: src/file-manager/fm-directory-view.c
@@ +154,3 @@
 static int scripts_directory_uri_length;
 
+static char *bulk_rename_tool;

If you use this global variable, you should initialize it to NULL here.

@@ +1882,3 @@
+have_bulk_rename_tool ()
+{
+	return (bulk_rename_tool && (*bulk_rename_tool != '\0'));

Could you please use "== NULL" and "!= NULL" explicitly when you check pointers? I know nautilus' coding style is not consistent about this, but we should do that for new code.

@@ +6103,3 @@
+	cmd = g_string_new (bulk_rename_tool);
+	for (walk = selection; walk; walk = walk->next) {
+		file = NAUTILUS_FILE (walk->data);

You don't need to cast walk->data.

@@ +6122,3 @@
+
+static void
+bulk_rename_tool_setting_changed_callback (GSettings *settings)

The signature of the "changed" signal of GSettings is (GSettings *, gchar *, gpointer), so this function should use that.

@@ +6150,3 @@
+			}
+		}
+		else {

Coding style: the curly braces and 'else' should all be on the same line.

@@ +8545,3 @@
+		gtk_action_set_sensitive (action, have_bulk_rename_tool ());
+	}
+	else {

Ditto.
Comment 27 Cosimo Cecchi 2010-10-20 12:46:24 UTC
(In reply to comment #25)
 
> > AFAICS this will connect a signal handler every time real_update_menus() is
> > called, which is wrong.
> 
> No, only the very first time. The bulk_rename_tool variable is global and
> shared
> among all views, and is only NULL at the very beginning. On consecutive calls, 
> if no bulk rename tool is registered, it will be "".
> 
> Just in case if there is some reason why g_settings_get_string() might
> return NULL that I am not aware of, I added a safety net in
> bulk_rename_tool_setting_changed_callback(). Otherwise, I left it as it
> was (except more elaborate comments). Please don't hesitate to throw this one
> back to me if I still didn't get it :-)

Yeah, you're right, that's connected only once. Although...

> > I think what I would do is:
> > - don't connect to any 'changed' signal coming from GSettings
> > - in have_bulk_rename_tool(), update your local stripped copy of the GSettings
> >   string
> > - in real_update_menus(), do basically what you do now, except for the if
> >   (block_rename_tool == NULL) {} block, which would go away.
> 
> Hm, I was thinking about that too, but changing the selection is a very common
> operation. I understand that GSettings is optimized for reading, but I was
> hesitant if it's really a good idea to read that rather exotic key with high
> frequency - especially when it's not really necessary.

...that global variable could just go away if you did what I suggested here. real_update_menus() already calls into GSettings many times, so that should not be a performance problem (and if it is, GSettings should be fixed and applications should not workaround it).
Comment 28 Holger Berndt 2010-10-31 16:23:39 UTC
Created attachment 173597 [details] [review]
Add possibility to register an external bulk rename tool

Thanks again for the thorough review, Cosimo.

> ...that global variable could just go away if you did what I suggested here.
> real_update_menus() already calls into GSettings many times, so that should not
> be a performance problem (and if it is, GSettings should be fixed and
> applications should not workaround it).

I changed the  patch so that now, GSettings is queried on selection changes,
and got rid of the locally cached copy.

> I think you should make it clearer whether this should be a full path to an
> executable file or the name of one in $PATH. It could also be safe to allow
> both, but this should be made clearer in the description.

Description updated (though a native English speaker could surely do a better job).
Like other command invokations in Nautilus, the patch uses
gdk_spawn_command_line_on_screen(), which searches the path.

> Note that in both cases, I think the setting should become an array of bytes
> ('ay' signature), as we are storing a filename, not an UTF-8 string.

Good point. Done.

> +static char *bulk_rename_tool;
> If you use this global variable, you should initialize it to NULL here.

Not applicable anymore.

> Could you please use "== NULL" and "!= NULL" explicitly when you check
> pointers?

Done.

> +        file = NAUTILUS_FILE (walk->data);
> You don't need to cast walk->data.

Done.

> The signature of the "changed" signal of GSettings is (GSettings *, gchar *,
> gpointer), so this function should use that.

Not applicable anymore.

> Coding style: the curly braces and 'else' should all be on the same line.

Done.
Comment 29 Cosimo Cecchi 2010-11-01 11:53:52 UTC
Review of attachment 173597 [details] [review]:

Thanks for the patch, looks good.
Comment 30 Holger Berndt 2010-11-01 16:29:14 UTC
Attachment 173597 [details] pushed as 27f14a8 - Add possibility to register an external bulk rename tool