If the _expression_ is empty, then by default _replacement_ will be added to the start of the filename. With *--all*, _replacement_ will be inserted in between every two characters of the filename, as well as at the start and end.
-Normally, only the final path component of a filename is updated. But if either _expression_ or _replacement_ contains a _/_, the full path is updated. This can cause a file to be moved between folders. Creating folders, and moving files between filesystems, is not supported. With *--symlink*, the update is always applied to the link's full path.
+Normally, only the final path component of a filename is updated. (Or with *--symlink*, only the final path component of the link.) But if either _expression_ or _replacement_ contains a _/_, the full path is updated. This can cause a file to be moved between folders. Creating folders, and moving files between filesystems, is not supported.
== INTERACTIVE MODE
static int all = 0;
static int last = 0;
-static int string_replace(char *from, char *to, char *s, char *orig, char **newname)
+/* Find the first place in `orig` where we'll perform a replacement. NULL if
+ there are no replacements to do. */
+static char *find_initial_replace(char *from, char *to, char *orig)
+{
+ char *search_start = orig;
+
+ if (strchr(from, '/') == NULL && strchr(to, '/') == NULL) {
+ /* We only want to search in the final path component. Don't
+ include the final '/' in that component; if `from` is empty,
+ we want it to first match after the '/', not before. */
+ search_start = strrchr(orig, '/');
+
+ if (search_start == NULL)
+ search_start = orig;
+ else
+ search_start++;
+ }
+
+ return strstr(search_start, from);
+}
+
+static int string_replace(char *from, char *to, char *orig, char **newname)
{
char *p, *q, *where;
size_t count = 0, fromlen = strlen(from);
- p = where = strstr(s, from);
+ p = where = find_initial_replace(from, to, orig);
if (where == NULL)
return 1;
count++;
}
target[ssz] = '\0';
- if (string_replace(from, to, target, target, &newname) != 0)
+ if (string_replace(from, to, target, &newname) != 0)
ret = 0;
if (ret == 1 && (nooverwrite || interactive) && lstat(newname, &sb) != 0)
static int do_file(char *from, char *to, char *s, int verbose, int noact,
int nooverwrite, int interactive)
{
- char *newname = NULL, *file=NULL;
+ char *newname = NULL;
int ret = 1;
struct stat sb;
warn(_("stat of %s failed"), s);
return 2;
}
- if (strchr(from, '/') == NULL && strchr(to, '/') == NULL) {
- file = strrchr(s, '/');
- /* We're going to search for `from` in `file`. If `from` is
- empty, we don't want it to match before the '/'. */
- if (file != NULL)
- file++;
- }
- if (file == NULL)
- file = s;
- if (string_replace(from, to, file, s, &newname) != 0)
+ if (string_replace(from, to, s, &newname) != 0)
return 0;
if ((nooverwrite || interactive) && access(newname, F_OK) != 0)
rename_ab
rename_ab/xa
== symlinks ==
-rename_aa/sublink.1: `rename/aa' -> `renxme/aa'
-rename_aa/sublink.2: `rename/aa' -> `renxme/aa'
-rename_aa/sublink.3: `rename/aa' -> `renxme/aa'
-rename_ab/sublink.1: `rename/aa' -> `renxme/aa'
-rename_ab/sublink.2: `rename/aa' -> `renxme/aa'
-rename_ab/sublink.3: `rename/aa' -> `renxme/aa'
-renxme/aa
-renxme/aa
-renxme/aa
-renxme/aa
-renxme/aa
-renxme/aa
+rename_aa/sublink.1: `rename/aa' -> `rename/xa'
+rename_aa/sublink.2: `rename/aa' -> `rename/xa'
+rename_aa/sublink.3: `rename/aa' -> `rename/xa'
+rename_ab/sublink.1: `rename/aa' -> `rename/xa'
+rename_ab/sublink.2: `rename/aa' -> `rename/xa'
+rename_ab/sublink.3: `rename/aa' -> `rename/xa'
+rename/xa
+rename/xa
+rename/xa
+rename/xa
+rename/xa
+rename/xa
== fullpath ==
`./rename_path1' -> `./rename_path2'
./rename_path2
rename_path_a
rename_path_b
rename_path_b/test2
+rename_link: `some/nonexistent/path' -> `some/nonexisten_ath'
+rename_link: `some/nonexisten_ath' -> `some/non/en_ath'
+rename_link: `some/non/en_ath' -> `some/non/xn_ath'
+some/non/xn_ath
== empty 'from' ==
`rename_test' -> `_rename_test'
`./rename_test' -> `./_rename_test'