diff options
author | G.raud Meyer | 2018-03-24 12:15:55 +0100 |
---|---|---|
committer | G.raud Meyer | 2018-04-09 16:05:44 +0200 |
commit | eb4aea8a4756be04655f31b286bc33b593f2689f (patch) | |
tree | 0f23158282acc3b82ea5b158c4f915c4a9c138ae /misc-utils/rename.c | |
parent | rename: skip faccessat() failure if AT_SYMLINK_NOFOLLOW is not a valid flag (diff) | |
download | kernel-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.c | 58 |
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: |