diff --git a/libcaja-private/caja-global-preferences.h b/libcaja-private/caja-global-preferences.h
index 832811574..4d978e6e1 100644
--- a/libcaja-private/caja-global-preferences.h
+++ b/libcaja-private/caja-global-preferences.h
@@ -209,6 +209,9 @@ typedef enum
#define CAJA_PREFERENCES_LOCKDOWN_COMMAND_LINE "disable-command-line"
#define CAJA_PREFERENCES_DISABLED_EXTENSIONS "disabled-extensions"
+/* bulk rename utility */
+#define CAJA_PREFERENCES_BULK_RENAME_TOOL "bulk-rename-tool"
+
void caja_global_preferences_init (void);
char *caja_global_preferences_get_default_folder_viewer_preference_as_iid (void);
diff --git a/libcaja-private/org.mate.caja.gschema.xml b/libcaja-private/org.mate.caja.gschema.xml
index 399efdc79..17de5838d 100644
--- a/libcaja-private/org.mate.caja.gschema.xml
+++ b/libcaja-private/org.mate.caja.gschema.xml
@@ -269,6 +269,11 @@
Whether to show desktop notifications
If set to true, Caja will show desktop notifications.
+
+ []
+ Bulk rename utility
+ If set, Nautilus will append URIs of selected files and treat the result as a command line for bulk renaming. Bulk rename applications can register themselves in this key by setting the key to a space-separated string of their executable name and any command line options. If the executable name is not set to a full path, it will be searched for in the search path.
+
diff --git a/src/caja-file-management-properties.c b/src/caja-file-management-properties.c
index 5a4368a7f..9e4a8827b 100644
--- a/src/caja-file-management-properties.c
+++ b/src/caja-file-management-properties.c
@@ -77,6 +77,8 @@
/* int enums */
#define CAJA_FILE_MANAGEMENT_PROPERTIES_THUMBNAIL_LIMIT_WIDGET "preview_image_size_combobox"
+#define CAJA_FILE_MANAGEMENT_PROPERTIES_BULK_RENAME_WIDGET "bulk_rename_entry"
+
static const char * const default_view_values[] =
{
"icon-view",
@@ -939,6 +941,17 @@ bind_builder_bool_inverted (GtkBuilder *builder,
"active", G_SETTINGS_BIND_INVERT_BOOLEAN);
}
+static void
+bind_builder_string_entry (GtkBuilder *builder,
+ GSettings *settings,
+ const char *widget_name,
+ const char *prefs)
+{
+ g_settings_bind (settings, prefs,
+ gtk_builder_get_object (builder, widget_name),
+ "text", G_SETTINGS_BIND_DEFAULT);
+}
+
static gboolean
enum_get_mapping (GValue *value,
GVariant *variant,
@@ -1136,6 +1149,9 @@ caja_file_management_properties_dialog_setup (GtkBuilder *builder, GtkWindow *wi
bind_builder_bool (builder, caja_preferences,
CAJA_FILE_MANAGEMENT_PROPERTIES_TRASH_DELETE_WIDGET,
CAJA_PREFERENCES_ENABLE_DELETE);
+ bind_builder_string_entry (builder, caja_preferences,
+ CAJA_FILE_MANAGEMENT_PROPERTIES_BULK_RENAME_WIDGET,
+ CAJA_PREFERENCES_BULK_RENAME_TOOL);
bind_builder_bool (builder, caja_preferences,
CAJA_FILE_MANAGEMENT_PROPERTIES_SHOW_HIDDEN_WIDGET,
CAJA_PREFERENCES_SHOW_HIDDEN_FILES);
diff --git a/src/caja-file-management-properties.ui b/src/caja-file-management-properties.ui
index 3207c800a..ed44c28e3 100644
--- a/src/caja-file-management-properties.ui
+++ b/src/caja-file-management-properties.ui
@@ -1161,6 +1161,83 @@
2
+
+
+
+ False
+ True
+ 3
+
+
1
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 7431c9635..ac936b651 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -6421,6 +6421,66 @@ real_action_redo (FMDirectoryView *view)
caja_undostack_manager_redo (manager, GTK_WIDGET (view), finish_undoredo_callback);
}
+static char *
+get_bulk_rename_tool (void)
+{
+ char *bulk_rename_tool;
+ g_settings_get (caja_preferences, CAJA_PREFERENCES_BULK_RENAME_TOOL, "^ay", &bulk_rename_tool);
+ return g_strstrip (bulk_rename_tool);
+}
+
+static gboolean
+have_bulk_rename_tool (void)
+{
+ char *bulk_rename_tool;
+ gboolean have_tool;
+
+ bulk_rename_tool = get_bulk_rename_tool ();
+ have_tool = ((bulk_rename_tool != NULL) && (*bulk_rename_tool != '\0'));
+ g_free (bulk_rename_tool);
+ return have_tool;
+}
+
+static void
+invoke_external_bulk_rename_utility (FMDirectoryView *view,
+ GList *selection)
+{
+ GString *cmd;
+ char *parameter;
+ char *quoted_parameter;
+ char *bulk_rename_tool;
+ GList *walk;
+ CajaFile *file;
+
+ /* assemble command line */
+ bulk_rename_tool = get_bulk_rename_tool ();
+ cmd = g_string_new (bulk_rename_tool);
+ g_free (bulk_rename_tool);
+ for (walk = selection; walk; walk = walk->next) {
+ file = walk->data;
+ parameter = caja_file_get_uri (file);
+ quoted_parameter = g_shell_quote (parameter);
+ g_free (parameter);
+ cmd = g_string_append (cmd, " ");
+ cmd = g_string_append (cmd, quoted_parameter);
+ g_free (quoted_parameter);
+ }
+
+ guint i = 0;
+
+ // Escape percents
+ for (i = 0; i < strlen(cmd->str); i++) {
+ if (cmd->str[i] == '%') {
+ g_string_insert_c(cmd, i++, '%');
+ }
+ }
+
+ /* spawning and error handling */
+ caja_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)),
+ cmd->str, cmd->str, FALSE, NULL);
+ g_string_free (cmd, TRUE);
+}
+
static void
real_action_rename (FMDirectoryView *view,
gboolean select_all)
@@ -6432,16 +6492,21 @@ real_action_rename (FMDirectoryView *view,
selection = fm_directory_view_get_selection (view);
if (selection_not_empty_in_menu_callback (view, selection)) {
- CajaFile *file;
-
- file = CAJA_FILE (selection->data);
-
- if (!select_all) {
+ /* If there is more than one file selected, invoke a batch renamer */
+ if (selection->next != NULL) {
+ if (have_bulk_rename_tool ()) {
+ invoke_external_bulk_rename_utility (view, selection);
+ }
+ } else {
+ CajaFile *file;
+ file = CAJA_FILE (selection->data);
+ if (!select_all) {
/* directories don't have a file extension, so
* they are always pre-selected as a whole */
- select_all = caja_file_is_directory (file);
+ select_all = caja_file_is_directory (file);
+ }
+ EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, file, select_all));
}
- EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, file, select_all));
}
caja_file_list_free (selection);
@@ -8915,9 +8980,16 @@ real_update_menus (FMDirectoryView *view)
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_RENAME);
- gtk_action_set_sensitive (action,
- selection_count == 1 &&
- fm_directory_view_can_rename_file (view, selection->data));
+
+ /* rename sensitivity depending on selection */
+ if (selection_count > 1) {
+ /* If multiple files are selected, sensitivity depends on whether a bulk renamer is registered. */
+ gtk_action_set_sensitive (action, have_bulk_rename_tool ());
+ } else {
+ gtk_action_set_sensitive (action,
+ selection_count == 1 &&
+ fm_directory_view_can_rename_file (view, selection->data));
+ }
action = gtk_action_group_get_action (view->details->dir_action_group,
FM_ACTION_NEW_FOLDER);