]>
Commit | Line | Data |
---|---|---|
eb63b9b8 KZ |
1 | /* |
2 | * rename.c - aeb 2000-01-01 | |
3 | * | |
4 | -------------------------------------------------------------- | |
5 | #!/bin/sh | |
6 | if [ $# -le 2 ]; then echo call: rename from to files; exit; fi | |
7 | FROM="$1" | |
8 | TO="$2" | |
9 | shift | |
10 | shift | |
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. | |
15 | */ | |
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | #include <stdlib.h> | |
19 | #include <errno.h> | |
d200a926 | 20 | #include <getopt.h> |
5a2a8177 JM |
21 | #include <unistd.h> |
22 | #include <sys/types.h> | |
23 | #include <sys/stat.h> | |
87f3feac | 24 | |
eb63b9b8 | 25 | #include "nls.h" |
87f3feac | 26 | #include "xalloc.h" |
d200a926 | 27 | #include "c.h" |
c05a80ca | 28 | #include "closestream.h" |
eb63b9b8 | 29 | |
d6cf9e16 SK |
30 | #define RENAME_EXIT_SOMEOK 2 |
31 | #define RENAME_EXIT_NOTHING 4 | |
32 | #define RENAME_EXIT_UNEXPLAINED 64 | |
33 | ||
5651128a | 34 | static int string_replace(char *from, char *to, char *s, char *orig, char **newname) |
d200a926 | 35 | { |
5651128a SK |
36 | char *p, *q, *where; |
37 | ||
38 | where = strstr(s, from); | |
39 | if (where == NULL) | |
40 | return 1; | |
41 | p = orig; | |
42 | *newname = xmalloc(strlen(orig) + strlen(to) + 1); | |
43 | q = *newname; | |
eb63b9b8 KZ |
44 | while (p < where) |
45 | *q++ = *p++; | |
46 | p = to; | |
47 | while (*p) | |
48 | *q++ = *p++; | |
5651128a | 49 | p = where + strlen(from); |
eb63b9b8 KZ |
50 | while (*p) |
51 | *q++ = *p++; | |
22853e4a | 52 | *q = 0; |
5651128a SK |
53 | return 0; |
54 | } | |
eb63b9b8 | 55 | |
5651128a SK |
56 | static int do_symlink(char *from, char *to, char *s, int verbose) |
57 | { | |
58 | char *newname = NULL, *target = NULL; | |
59 | int ret = 1; | |
60 | struct stat sb; | |
61 | ||
62 | if (lstat(s, &sb) == -1) { | |
63 | warn(_("%s: lstat failed"), s); | |
64 | return 2; | |
65 | } | |
66 | if (!S_ISLNK(sb.st_mode)) { | |
67 | warnx(_("%s: not a symbolic link"), s); | |
68 | return 2; | |
69 | } | |
70 | target = xmalloc(sb.st_size + 1); | |
71 | if (readlink(s, target, sb.st_size + 1) < 0) { | |
72 | warn(_("%s: readlink failed"), s); | |
73 | free(target); | |
74 | return 2; | |
75 | } | |
76 | target[sb.st_size] = '\0'; | |
77 | if (string_replace(from, to, target, target, &newname)) | |
78 | ret = 0; | |
79 | else if (0 > unlink(s)) { | |
80 | warn(_("%s: unlink failed"), s); | |
81 | ret = 2; | |
82 | } else if (symlink(newname, s) != 0) { | |
83 | warn(_("%s: symlinking to %s failed"), s, newname); | |
84 | ret = 2; | |
5a2a8177 | 85 | } |
5651128a SK |
86 | if (verbose && ret == 1) |
87 | printf("%s: `%s' -> `%s'\n", s, target, newname); | |
d200a926 | 88 | free(newname); |
23b4715b | 89 | free(target); |
d6cf9e16 | 90 | return ret; |
eb63b9b8 KZ |
91 | } |
92 | ||
5651128a SK |
93 | static int do_file(char *from, char *to, char *s, int verbose) |
94 | { | |
95 | char *newname = NULL, *file; | |
96 | int ret = 1; | |
97 | ||
98 | file = rindex(s, '/'); | |
99 | if (file == NULL) | |
100 | file = s; | |
101 | if (string_replace(from, to, file, s, &newname)) | |
102 | return 0; | |
103 | else if (rename(s, newname) != 0) { | |
104 | warn(_("%s: rename to %s failed"), s, newname); | |
105 | ret = 2; | |
106 | } | |
107 | if (verbose && ret == 1) | |
108 | printf("`%s' -> `%s'\n", s, newname); | |
109 | free(newname); | |
110 | return ret; | |
111 | } | |
112 | ||
d200a926 SK |
113 | static void __attribute__ ((__noreturn__)) usage(FILE * out) |
114 | { | |
540dfebe | 115 | fputs(USAGE_HEADER, out); |
d200a926 | 116 | fprintf(out, |
09af3db4 | 117 | _(" %s [options] <expression> <replacement> <file>...\n"), |
d200a926 | 118 | program_invocation_short_name); |
540dfebe SK |
119 | fputs(USAGE_OPTIONS, out); |
120 | fputs(_(" -v, --verbose explain what is being done\n"), out); | |
09af3db4 | 121 | fputs(_(" -s, --symlink act on the target of symlinks\n"), out); |
540dfebe SK |
122 | fputs(USAGE_SEPARATOR, out); |
123 | fputs(USAGE_HELP, out); | |
124 | fputs(USAGE_VERSION, out); | |
125 | fprintf(out, USAGE_MAN_TAIL("rename(1)")); | |
d200a926 SK |
126 | exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); |
127 | } | |
eb63b9b8 | 128 | |
d200a926 SK |
129 | int main(int argc, char **argv) |
130 | { | |
131 | char *from, *to; | |
5651128a SK |
132 | int i, c, ret = 0, verbose = 0; |
133 | int (*do_rename)(char *from, char *to, char *s, int verbose) = do_file; | |
d200a926 SK |
134 | |
135 | static const struct option longopts[] = { | |
136 | {"verbose", no_argument, NULL, 'v'}, | |
137 | {"version", no_argument, NULL, 'V'}, | |
138 | {"help", no_argument, NULL, 'h'}, | |
5a2a8177 | 139 | {"symlink", no_argument, NULL, 's'}, |
d200a926 SK |
140 | {NULL, 0, NULL, 0} |
141 | }; | |
eb63b9b8 KZ |
142 | |
143 | setlocale(LC_ALL, ""); | |
144 | bindtextdomain(PACKAGE, LOCALEDIR); | |
145 | textdomain(PACKAGE); | |
c05a80ca | 146 | atexit(close_stdout); |
eb63b9b8 | 147 | |
5a2a8177 | 148 | while ((c = getopt_long(argc, argv, "vsVh", longopts, NULL)) != -1) |
d200a926 SK |
149 | switch (c) { |
150 | case 'v': | |
151 | verbose = 1; | |
152 | break; | |
5a2a8177 | 153 | case 's': |
5651128a | 154 | do_rename = do_symlink; |
5a2a8177 | 155 | break; |
d200a926 | 156 | case 'V': |
c717b032 | 157 | printf(UTIL_LINUX_VERSION); |
d200a926 SK |
158 | return EXIT_SUCCESS; |
159 | case 'h': | |
160 | usage(stdout); | |
161 | default: | |
162 | usage(stderr); | |
eb63b9b8 | 163 | } |
d200a926 SK |
164 | |
165 | argc -= optind; | |
166 | argv += optind; | |
eb63b9b8 KZ |
167 | |
168 | if (argc < 3) { | |
8c219bf4 | 169 | warnx(_("not enough arguments")); |
d200a926 | 170 | usage(stderr); |
eb63b9b8 KZ |
171 | } |
172 | ||
d200a926 SK |
173 | from = argv[0]; |
174 | to = argv[1]; | |
175 | ||
176 | for (i = 2; i < argc; i++) | |
5651128a | 177 | ret |= do_rename(from, to, argv[i], verbose); |
d6cf9e16 SK |
178 | |
179 | switch (ret) { | |
180 | case 0: | |
181 | return RENAME_EXIT_NOTHING; | |
182 | case 1: | |
183 | return EXIT_SUCCESS; | |
184 | case 2: | |
185 | return EXIT_FAILURE; | |
186 | case 3: | |
187 | return RENAME_EXIT_SOMEOK; | |
188 | default: | |
189 | return RENAME_EXIT_UNEXPLAINED; | |
190 | } | |
eb63b9b8 | 191 | } |