]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
rename: add option --interactive to ask before overwriting
authorG.raud Meyer <graud@gmx.com>
Sat, 24 Mar 2018 11:15:55 +0000 (12:15 +0100)
committerG.raud Meyer <graud@gmx.com>
Mon, 9 Apr 2018 14:05:44 +0000 (16:05 +0200)
The option name -i/--interactive is picked from mv(1) and cp(1) from GNU
and BSD.

Also update the manpage.

misc-utils/rename.1
misc-utils/rename.c

index df329461b49bb24c73272a9d51b82029bcb9119d..142a17fc5ff917b1ddf67a4c404bf91b8f4a1609 100644 (file)
@@ -32,6 +32,9 @@ Do not overwrite existing files.  When
 .BR \-\-symlink
 is active, do not overwrite symlinks pointing to existing targets.
 .TP
+.BR \-i , " \-\-interactive"
+Ask before overwriting existing files.
+.TP
 .BR \-V , " \-\-version"
 Display version information and exit.
 .TP
index 8f5d41a695c98319c94d5aa9fea272f5a9b83faa..d98e9d8f9079be881224231ed011f7bbe04aed7e 100644 (file)
@@ -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: