]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/rename.c
tests: fincore/count, skip unsupported FS
[thirdparty/util-linux.git] / misc-utils / rename.c
CommitLineData
eb63b9b8
KZ
1/*
2 * rename.c - aeb 2000-01-01
3 *
4--------------------------------------------------------------
5#!/bin/sh
6if [ $# -le 2 ]; then echo call: rename from to files; exit; fi
7FROM="$1"
8TO="$2"
9shift
10shift
11for 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 34static 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
990bf1f0 56static int do_symlink(char *from, char *to, char *s, int verbose, int noact)
5651128a
SK
57{
58 char *newname = NULL, *target = NULL;
59 int ret = 1;
60 struct stat sb;
61
62 if (lstat(s, &sb) == -1) {
fc14ceba 63 warn(_("stat of %s failed"), s);
5651128a
SK
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;
990bf1f0 79 else if (!noact && 0 > unlink(s)) {
5651128a
SK
80 warn(_("%s: unlink failed"), s);
81 ret = 2;
990bf1f0 82 } else if (!noact && symlink(newname, s) != 0) {
5651128a
SK
83 warn(_("%s: symlinking to %s failed"), s, newname);
84 ret = 2;
5a2a8177 85 }
990bf1f0 86 if (verbose && (noact || ret == 1))
5651128a 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
990bf1f0 93static int do_file(char *from, char *to, char *s, int verbose, int noact)
5651128a 94{
9fa6088a 95 char *newname = NULL, *file=NULL;
5651128a
SK
96 int ret = 1;
97
9fa6088a
AH
98 if (strchr(from, '/') == NULL && strchr(to, '/') == NULL)
99 file = strrchr(s, '/');
5651128a
SK
100 if (file == NULL)
101 file = s;
102 if (string_replace(from, to, file, s, &newname))
103 return 0;
990bf1f0 104 else if (!noact && rename(s, newname) != 0) {
5651128a
SK
105 warn(_("%s: rename to %s failed"), s, newname);
106 ret = 2;
107 }
990bf1f0 108 if (verbose && (noact || ret == 1))
5651128a
SK
109 printf("`%s' -> `%s'\n", s, newname);
110 free(newname);
111 return ret;
112}
113
d200a926
SK
114static void __attribute__ ((__noreturn__)) usage(FILE * out)
115{
540dfebe 116 fputs(USAGE_HEADER, out);
d200a926 117 fprintf(out,
09af3db4 118 _(" %s [options] <expression> <replacement> <file>...\n"),
d200a926 119 program_invocation_short_name);
451dbcfa
BS
120
121 fputs(USAGE_SEPARATOR, out);
122 fputs(_("Rename files.\n"), out);
123
540dfebe
SK
124 fputs(USAGE_OPTIONS, out);
125 fputs(_(" -v, --verbose explain what is being done\n"), out);
09af3db4 126 fputs(_(" -s, --symlink act on the target of symlinks\n"), out);
990bf1f0 127 fputs(_(" -n, --no-act do not make any changes\n"), out);
540dfebe
SK
128 fputs(USAGE_SEPARATOR, out);
129 fputs(USAGE_HELP, out);
130 fputs(USAGE_VERSION, out);
131 fprintf(out, USAGE_MAN_TAIL("rename(1)"));
d200a926
SK
132 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
133}
eb63b9b8 134
d200a926
SK
135int main(int argc, char **argv)
136{
137 char *from, *to;
990bf1f0
AR
138 int i, c, ret = 0, verbose = 0, noact = 0;
139 int (*do_rename)(char *from, char *to, char *s, int verbose, int noact) = do_file;
d200a926
SK
140
141 static const struct option longopts[] = {
142 {"verbose", no_argument, NULL, 'v'},
143 {"version", no_argument, NULL, 'V'},
144 {"help", no_argument, NULL, 'h'},
990bf1f0 145 {"no-act", no_argument, NULL, 'n'},
5a2a8177 146 {"symlink", no_argument, NULL, 's'},
d200a926
SK
147 {NULL, 0, NULL, 0}
148 };
eb63b9b8
KZ
149
150 setlocale(LC_ALL, "");
151 bindtextdomain(PACKAGE, LOCALEDIR);
152 textdomain(PACKAGE);
c05a80ca 153 atexit(close_stdout);
eb63b9b8 154
990bf1f0 155 while ((c = getopt_long(argc, argv, "vsVhn", longopts, NULL)) != -1)
d200a926
SK
156 switch (c) {
157 case 'v':
158 verbose = 1;
159 break;
990bf1f0
AR
160 case 'n':
161 noact = 1;
162 break;
5a2a8177 163 case 's':
5651128a 164 do_rename = do_symlink;
5a2a8177 165 break;
d200a926 166 case 'V':
c717b032 167 printf(UTIL_LINUX_VERSION);
d200a926
SK
168 return EXIT_SUCCESS;
169 case 'h':
170 usage(stdout);
990bf1f0 171 /* fallthrough */
d200a926 172 default:
677ec86c 173 errtryhelp(EXIT_FAILURE);
eb63b9b8 174 }
d200a926
SK
175
176 argc -= optind;
177 argv += optind;
eb63b9b8
KZ
178
179 if (argc < 3) {
8c219bf4 180 warnx(_("not enough arguments"));
d200a926 181 usage(stderr);
eb63b9b8
KZ
182 }
183
d200a926
SK
184 from = argv[0];
185 to = argv[1];
186
187 for (i = 2; i < argc; i++)
990bf1f0 188 ret |= do_rename(from, to, argv[i], verbose, noact);
d6cf9e16
SK
189
190 switch (ret) {
191 case 0:
192 return RENAME_EXIT_NOTHING;
193 case 1:
194 return EXIT_SUCCESS;
195 case 2:
196 return EXIT_FAILURE;
197 case 3:
198 return RENAME_EXIT_SOMEOK;
199 default:
200 return RENAME_EXIT_UNEXPLAINED;
201 }
eb63b9b8 202}