summaryrefslogtreecommitdiffstats
path: root/misc-utils/rename.c
diff options
context:
space:
mode:
authorG.raud Meyer2018-03-24 12:15:55 +0100
committerG.raud Meyer2018-04-09 16:05:44 +0200
commiteb4aea8a4756be04655f31b286bc33b593f2689f (patch)
tree0f23158282acc3b82ea5b158c4f915c4a9c138ae /misc-utils/rename.c
parentrename: skip faccessat() failure if AT_SYMLINK_NOFOLLOW is not a valid flag (diff)
downloadkernel-qcow2-util-linux-eb4aea8a4756be04655f31b286bc33b593f2689f.tar.gz
kernel-qcow2-util-linux-eb4aea8a4756be04655f31b286bc33b593f2689f.tar.xz
kernel-qcow2-util-linux-eb4aea8a4756be04655f31b286bc33b593f2689f.zip
rename: add option --interactive to ask before overwriting
The option name -i/--interactive is picked from mv(1) and cp(1) from GNU and BSD. Also update the manpage.
Diffstat (limited to 'misc-utils/rename.c')
-rw-r--r--misc-utils/rename.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/misc-utils/rename.c b/misc-utils/rename.c
index 8f5d41a69..d98e9d8f9 100644
--- a/misc-utils/rename.c
+++ b/misc-utils/rename.c
@@ -27,6 +27,7 @@ for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
#include "xalloc.h"
#include "c.h"
#include "closestream.h"
+#include "rpmatch.h"
#define RENAME_EXIT_SOMEOK 2
#define RENAME_EXIT_NOTHING 4
@@ -54,7 +55,30 @@ static int string_replace(char *from, char *to, char *s, char *orig, char **newn
return 0;
}
-static int do_symlink(char *from, char *to, char *s, int verbose, int noact, int nooverwrite)
+static int ask(char *name)
+{
+ int c;
+ char buf[2];
+ printf(_("%s: overwrite `%s'? "), program_invocation_short_name, name);
+ fflush(stdout);
+ if ((c = fgetc(stdin)) == EOF) {
+ buf[0] = '\0';
+ clearerr(stdin); errno = 0;
+ printf("\n");
+ }
+ else {
+ buf[0] = c; buf[1] = '\0';
+ if (c != '\n')
+ while ((c = fgetc(stdin)) != '\n' && c != EOF);
+ }
+ if (rpmatch(buf) == RPMATCH_YES)
+ return 0;
+ else
+ return 1;
+}
+
+static int do_symlink(char *from, char *to, char *s, int verbose, int noact,
+ int nooverwrite, int interactive)
{
char *newname = NULL, *target = NULL;
int ret = 1;
@@ -87,10 +111,14 @@ static int do_symlink(char *from, char *to, char *s, int verbose, int noact, int
if (string_replace(from, to, target, target, &newname))
ret = 0;
- if (ret == 1 && nooverwrite && lstat(target, &sb) == 0) {
+ if (ret == 1 && (nooverwrite || interactive) && lstat(newname, &sb) != 0)
+ nooverwrite = interactive = 0;
+
+ if ( ret == 1 &&
+ (nooverwrite || (interactive && (noact || ask(newname) != 0))) )
+ {
if (verbose)
printf(_("Skipping existing link: `%s' -> `%s'\n"), s, target);
-
ret = 0;
}
@@ -111,7 +139,8 @@ static int do_symlink(char *from, char *to, char *s, int verbose, int noact, int
return ret;
}
-static int do_file(char *from, char *to, char *s, int verbose, int noact, int nooverwrite)
+static int do_file(char *from, char *to, char *s, int verbose, int noact,
+ int nooverwrite, int interactive)
{
char *newname = NULL, *file=NULL;
int ret = 1;
@@ -128,7 +157,10 @@ static int do_file(char *from, char *to, char *s, int verbose, int noact, int no
if (string_replace(from, to, file, s, &newname))
return 0;
- if (nooverwrite && access(newname, F_OK) == 0) {
+ if ((nooverwrite || interactive) && access(newname, F_OK) != 0)
+ nooverwrite = interactive = 0;
+
+ if (nooverwrite || (interactive && (noact || ask(newname) != 0))) {
if (verbose)
printf(_("Skipping existing file: `%s'\n"), newname);
ret = 0;
@@ -159,6 +191,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -s, --symlink act on the target of symlinks\n"), out);
fputs(_(" -n, --no-act do not make any changes\n"), out);
fputs(_(" -o, --no-overwrite don't overwrite existing files\n"), out);
+ fputs(_(" -i, --interactive prompt before overwrite\n"), out);
fputs(USAGE_SEPARATOR, out);
printf(USAGE_HELP_OPTIONS(21));
printf(USAGE_MAN_TAIL("rename(1)"));
@@ -168,8 +201,9 @@ static void __attribute__((__noreturn__)) usage(void)
int main(int argc, char **argv)
{
char *from, *to;
- int i, c, ret = 0, verbose = 0, noact = 0, nooverwrite = 0;
- int (*do_rename)(char *from, char *to, char *s, int verbose, int noact, int nooverwrite) = do_file;
+ int i, c, ret = 0, verbose = 0, noact = 0, nooverwrite = 0, interactive = 0;
+ int (*do_rename)(char *from, char *to, char *s, int verbose, int noact,
+ int nooverwrite, int interactive) = do_file;
static const struct option longopts[] = {
{"verbose", no_argument, NULL, 'v'},
@@ -177,6 +211,7 @@ int main(int argc, char **argv)
{"help", no_argument, NULL, 'h'},
{"no-act", no_argument, NULL, 'n'},
{"no-overwrite", no_argument, NULL, 'o'},
+ {"interactive", no_argument, NULL, 'i'},
{"symlink", no_argument, NULL, 's'},
{NULL, 0, NULL, 0}
};
@@ -186,7 +221,7 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "vsVhno", longopts, NULL)) != -1)
+ while ((c = getopt_long(argc, argv, "vsVhnoi", longopts, NULL)) != -1)
switch (c) {
case 'n':
noact = 1;
@@ -196,6 +231,11 @@ int main(int argc, char **argv)
break;
case 'o':
nooverwrite = 1;
+ interactive = 0;
+ break;
+ case 'i':
+ interactive = 1;
+ nooverwrite = 0;
break;
case 's':
do_rename = do_symlink;
@@ -224,7 +264,7 @@ int main(int argc, char **argv)
return RENAME_EXIT_NOTHING;
for (i = 2; i < argc; i++)
- ret |= do_rename(from, to, argv[i], verbose, noact, nooverwrite);
+ ret |= do_rename(from, to, argv[i], verbose, noact, nooverwrite, interactive);
switch (ret) {
case 0: