diff --git a/shell/e-shell-migrate.c b/shell/e-shell-migrate.c
index f47a5e7..6a64ca4 100644
--- a/shell/e-shell-migrate.c
+++ b/shell/e-shell-migrate.c
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
+#include <libedataserver/e-data-server-util.h>
 #include <libedataserver/e-xml-utils.h>
 
 #include "e-util/e-alert-dialog.h"
@@ -38,6 +39,8 @@
 #define GCONF_LAST_VERSION_KEY	"/apps/evolution/last_version"
 
 /******************** Begin XDG Base Directory Migration ********************/
+static void
+shell_xdg_migrate_process_corrections (GHashTable *corrections);
 
 /* These are the known EShellBackend names as of Evolution 3.0 */
 static const gchar *shell_backend_names[] =
@@ -78,6 +81,66 @@ shell_xdg_migrate_rename (const gchar *old_filename,
 	return success;
 }
 
+
+static gboolean
+shell_xdg_migrate_rename_files (const gchar *src_directory,
+                                 const gchar *dst_directory)
+{
+	GDir *dir;
+	GHashTable *corrections;
+	const gchar *basename;
+	gchar *old_base_dir;
+
+	dir = g_dir_open (src_directory, 0, NULL);
+	if (dir == NULL)
+		return FALSE;
+
+	/* This is to avoid renaming files which we're iterating over the
+	 * directory.  POSIX says the outcome of that is unspecified. */
+	corrections = g_hash_table_new_full (
+		g_str_hash, g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_free);
+
+	g_mkdir_with_parents (dst_directory, 0700);
+
+	while ((basename = g_dir_read_name (dir)) != NULL) {
+		gchar *old_filename;
+		gchar *new_filename;
+		gchar *new_base_dir;
+		gchar *pos;
+		GString *result = g_string_new(0);
+
+		old_base_dir = g_build_filename (g_get_home_dir(), ".evolution", NULL);
+		e_filename_make_safe(old_base_dir);
+		new_base_dir = g_strdup(e_get_user_data_dir());
+		e_filename_make_safe(new_base_dir);
+		result = g_string_append(result, basename);
+		pos = strstr(basename, old_base_dir);
+		result = g_string_erase(result, pos-basename, strlen(old_base_dir));
+		result = g_string_insert(result, pos-basename, new_base_dir);
+
+		old_filename = g_build_filename (src_directory, basename, NULL);
+		new_filename = g_build_filename (dst_directory, result->str, NULL);
+
+		g_string_free(result, 0);
+
+		g_hash_table_insert (corrections, old_filename, new_filename);
+	}
+
+	g_dir_close (dir);
+
+	shell_xdg_migrate_process_corrections (corrections);
+	g_hash_table_destroy (corrections);
+
+	/* It's tempting to want to remove the source directory here.
+	 * Don't.  We might be iterating over the source directory's
+	 * parent directory, and removing the source directory would
+	 * screw up the iteration. */
+
+	return TRUE;
+}
+
 static gboolean
 shell_xdg_migrate_rmdir (const gchar *dirname)
 {
@@ -237,7 +300,7 @@ shell_xdg_migrate_config_dir_common (EShell *shell,
 
 	old_filename = g_build_filename (old_config_dir, "views", NULL);
 	new_filename = g_build_filename (new_config_dir, "views", NULL);
-	shell_xdg_migrate_rename (old_filename, new_filename);
+	shell_xdg_migrate_rename_files (old_filename, new_filename);
 	g_free (old_filename);
 	g_free (new_filename);
 
