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
;
110 if (strchr(from
, '/') == NULL
&& strchr(to
, '/') == NULL
)
111 file
= strrchr(s
, '/');
114 if (string_replace(from
, to
, file
, s
, &newname
))
116 if (nooverwrite
&& stat(newname
, &sb
) == 0) {
117 printf(_("Skipping existing file: `%s'\n"), newname
);
120 else if (!noact
&& rename(s
, newname
) != 0) {
121 warn(_("%s: rename to %s failed"), s
, newname
);
124 if (verbose
&& (noact
|| ret
== 1))
125 printf("`%s' -> `%s'\n", s
, newname
);
130 static void __attribute__ ((__noreturn__
)) usage(FILE * out
)
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 fputs(USAGE_HELP
, out
);
147 fputs(USAGE_VERSION
, out
);
148 fprintf(out
, USAGE_MAN_TAIL("rename(1)"));
149 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
152 int main(int argc
, char **argv
)
155 int i
, c
, ret
= 0, verbose
= 0, noact
= 0, nooverwrite
= 0;
156 int (*do_rename
)(char *from
, char *to
, char *s
, int verbose
, int noact
, int nooverwrite
) = do_file
;
158 static const struct option longopts
[] = {
159 {"verbose", no_argument
, NULL
, 'v'},
160 {"version", no_argument
, NULL
, 'V'},
161 {"help", no_argument
, NULL
, 'h'},
162 {"no-act", no_argument
, NULL
, 'n'},
163 {"no-overwrite", no_argument
, NULL
, 'o'},
164 {"symlink", no_argument
, NULL
, 's'},
168 setlocale(LC_ALL
, "");
169 bindtextdomain(PACKAGE
, LOCALEDIR
);
171 atexit(close_stdout
);
173 while ((c
= getopt_long(argc
, argv
, "vsVhno", longopts
, NULL
)) != -1)
185 do_rename
= do_symlink
;
188 printf(UTIL_LINUX_VERSION
);
194 errtryhelp(EXIT_FAILURE
);
201 warnx(_("not enough arguments"));
208 for (i
= 2; i
< argc
; i
++)
209 ret
|= do_rename(from
, to
, argv
[i
], verbose
, noact
, nooverwrite
);
213 return RENAME_EXIT_NOTHING
;
219 return RENAME_EXIT_SOMEOK
;
221 return RENAME_EXIT_UNEXPLAINED
;