2 * rename.c - aeb 2000-01-01
4 --------------------------------------------------------------
6 if [ $# -le 2 ]; then echo call: rename from to files; exit; fi
11 for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
12 --------------------------------------------------------------
13 * This shell script will do renames of files, but may fail
14 * in cases involving special characters. Here a C version.
22 #include <sys/types.h>
28 #include "closestream.h"
30 #define RENAME_EXIT_SOMEOK 2
31 #define RENAME_EXIT_NOTHING 4
32 #define RENAME_EXIT_UNEXPLAINED 64
34 static int string_replace(char *from
, char *to
, char *s
, char *orig
, char **newname
)
38 where
= strstr(s
, from
);
42 *newname
= xmalloc(strlen(orig
) + strlen(to
) + 1);
49 p
= where
+ strlen(from
);
56 static int do_symlink(char *from
, char *to
, char *s
, int verbose
, int noact
, int nooverwrite
)
58 char *newname
= NULL
, *target
= NULL
;
62 if (lstat(s
, &sb
) == -1) {
63 warn(_("stat of %s failed"), s
);
66 if (!S_ISLNK(sb
.st_mode
)) {
67 warnx(_("%s: not a symbolic link"), s
);
70 target
= xmalloc(sb
.st_size
+ 1);
71 if (readlink(s
, target
, sb
.st_size
+ 1) < 0) {
72 warn(_("%s: readlink failed"), s
);
76 target
[sb
.st_size
] = '\0';
77 if (string_replace(from
, to
, target
, target
, &newname
))
80 if (ret
== 1 && nooverwrite
&& lstat(newname
, &sb
) == 0) {
82 printf(_("Skipping existing link: `%s'\n"), newname
);
88 if (!noact
&& 0 > unlink(s
)) {
89 warn(_("%s: unlink failed"), s
);
91 } else if (!noact
&& symlink(newname
, s
) != 0) {
92 warn(_("%s: symlinking to %s failed"), s
, newname
);
96 if (verbose
&& (noact
|| ret
== 1))
98 printf("%s: `%s' -> `%s'\n", s
, target
, newname
);
104 static int do_file(char *from
, char *to
, char *s
, int verbose
, int noact
, int nooverwrite
)
106 char *newname
= NULL
, *file
=NULL
;
109 if (strchr(from
, '/') == NULL
&& strchr(to
, '/') == NULL
)
110 file
= strrchr(s
, '/');
113 if (string_replace(from
, to
, file
, s
, &newname
))
115 if (nooverwrite
&& access(newname
, F_OK
) == 0) {
116 printf(_("Skipping existing file: `%s'\n"), newname
);
119 else if (!noact
&& rename(s
, newname
) != 0) {
120 warn(_("%s: rename to %s failed"), s
, newname
);
123 if (verbose
&& (noact
|| ret
== 1))
124 printf("`%s' -> `%s'\n", s
, newname
);
129 static void __attribute__((__noreturn__
)) usage(void)
132 fputs(USAGE_HEADER
, out
);
134 _(" %s [options] <expression> <replacement> <file>...\n"),
135 program_invocation_short_name
);
137 fputs(USAGE_SEPARATOR
, out
);
138 fputs(_("Rename files.\n"), out
);
140 fputs(USAGE_OPTIONS
, out
);
141 fputs(_(" -v, --verbose explain what is being done\n"), out
);
142 fputs(_(" -s, --symlink act on the target of symlinks\n"), out
);
143 fputs(_(" -n, --no-act do not make any changes\n"), out
);
144 fputs(_(" -o, --no-overwrite don't overwrite existing files\n"), out
);
145 fputs(USAGE_SEPARATOR
, out
);
146 printf(USAGE_HELP_OPTIONS(21));
147 printf(USAGE_MAN_TAIL("rename(1)"));
151 int main(int argc
, char **argv
)
154 int i
, c
, ret
= 0, verbose
= 0, noact
= 0, nooverwrite
= 0;
155 int (*do_rename
)(char *from
, char *to
, char *s
, int verbose
, int noact
, int nooverwrite
) = do_file
;
157 static const struct option longopts
[] = {
158 {"verbose", no_argument
, NULL
, 'v'},
159 {"version", no_argument
, NULL
, 'V'},
160 {"help", no_argument
, NULL
, 'h'},
161 {"no-act", no_argument
, NULL
, 'n'},
162 {"no-overwrite", no_argument
, NULL
, 'o'},
163 {"symlink", no_argument
, NULL
, 's'},
167 setlocale(LC_ALL
, "");
168 bindtextdomain(PACKAGE
, LOCALEDIR
);
170 atexit(close_stdout
);
172 while ((c
= getopt_long(argc
, argv
, "vsVhno", longopts
, NULL
)) != -1)
184 do_rename
= do_symlink
;
187 printf(UTIL_LINUX_VERSION
);
192 errtryhelp(EXIT_FAILURE
);
199 warnx(_("not enough arguments"));
200 errtryhelp(EXIT_FAILURE
);
206 if (!strcmp(from
, to
))
207 return RENAME_EXIT_NOTHING
;
209 for (i
= 2; i
< argc
; i
++)
210 ret
|= do_rename(from
, to
, argv
[i
], verbose
, noact
, nooverwrite
);
214 return RENAME_EXIT_NOTHING
;
220 return RENAME_EXIT_SOMEOK
;
222 return RENAME_EXIT_UNEXPLAINED
;