bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: rm issue


From: Eric Blake
Subject: Re: rm issue
Date: Sat, 03 Dec 2005 14:00:02 -0700
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Paul Eggert on 12/2/2005 2:00 PM:
> However, we could have an option along those lines.  Users who prefer
> that behavior then could alias "rm" to rm-with-the-option.
> 
> FreeBSD has an -I option, with the following meaning:
> 
>      -I        Request confirmation once if more than three files are being
>                removed or if a directory is being recursively removed.  This
>                is a far less intrusive option than -i yet provides almost
>                the same level of protection against mistakes.
> 
> Would that suffice?

Here's my attempt at this idea.  Comments appreciated, and I would also
need to patch the testsuite:

ChangeLog:
2005-12-03  Eric Blake  <address@hidden>

        * TODO: Remove entry for implementing rm -I.
        * NEWS: Document rm -I, along with change to rm --interactive.
        * src/rm.c (INTERACTIVE_OPTION): New enum value.
        (interactive_type): New enum.
        (long_opts): Let interactive take an optional argument.
        (interactive_args, interactive_types): New option arguments.
        (usage): Document -I, --interactive=WHEN.  Use program_name
        instead of a basename.
        (main): New -I option, new behavior to --interactive.

doc/ChangeLog:
2005-12-03  Eric Blake  <address@hidden>

        * coreutils.texi (rm invocation): Document new -I option, and new
        --interactive behavior.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFDkgdS84KuGfSFAYARAuXUAJsGW02BHBzHAr/Fj8MqTNuCdrjTPQCfTTL5
8anvwJZoVpkMYL1hw+5WVZo=
=KtI5
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /cvsroot/coreutils/coreutils/NEWS,v
retrieving revision 1.349
diff -u -p -r1.349 NEWS
--- NEWS        26 Nov 2005 07:51:27 -0000      1.349
+++ NEWS        3 Dec 2005 20:50:26 -0000
@@ -22,6 +22,14 @@ GNU coreutils NEWS                      
   However, the 'locale' time style now behaves like 'posix-long-iso'
   if your locale settings appear to be messed up.  This change
   attempts to have the default be the best of both worlds.
+
+  rm --interactive now takes an optional argument, with the default
+  behavior of --interactive='once' (or -I).  This new behavior prompts
+  once if rm is invoked recursively or if more than three files are
+  being deleted, which is less intrusive than prompting for every file
+  but provides almost the same level of protection against mistakes.
+  To get the old behavior of prompting for every file, use -i or
+  --interactive='always'.
 
 ** Scheduled for removal
 
Index: TODO
===================================================================
RCS file: /cvsroot/coreutils/coreutils/TODO,v
retrieving revision 1.101
diff -u -p -r1.101 TODO
--- TODO        16 Oct 2005 10:36:02 -0000      1.101
+++ TODO        3 Dec 2005 20:50:26 -0000
@@ -215,9 +215,3 @@ Adapt tools like wc, tr, fmt, etc. (most
   (preferably `no') cost when operating in single-byte mode.
 
 Remove all uses of the `register' keyword
-
-rm: add support for a -I option, like that from FreeBSD's rm:
-   -I    Request confirmation once if more than three files are being
-         removed or if a directory is being recursively removed.  This
-         is a far less intrusive option than -i yet provides almost
-         the same level of protection against mistakes.
Index: src/rm.c
===================================================================
RCS file: /cvsroot/coreutils/coreutils/src/rm.c,v
retrieving revision 1.136
diff -u -p -r1.136 rm.c
--- src/rm.c    2 Nov 2005 21:53:20 -0000       1.136
+++ src/rm.c    3 Dec 2005 20:50:26 -0000
@@ -49,6 +49,7 @@
 #include <assert.h>
 
 #include "system.h"
+#include "argmatch.h"
 #include "dirname.h"
 #include "error.h"
 #include "lstat.h"
@@ -56,6 +57,7 @@
 #include "quotearg.h"
 #include "remove.h"
 #include "root-dev-ino.h"
+#include "yesno.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "rm"
@@ -70,16 +72,24 @@ char *program_name;
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
 {
-  NO_PRESERVE_ROOT = CHAR_MAX + 1,
+  INTERACTIVE_OPTION = CHAR_MAX + 1,
+  NO_PRESERVE_ROOT,
   PRESERVE_ROOT,
   PRESUME_INPUT_TTY_OPTION
 };
 
+enum interactive_type
+  {
+    interactive_never,         /* 0: no option or --interactive=never */
+    interactive_once,          /* 1: default, -I or --interactive=once */
+    interactive_always         /* 2: -i or --interactive=always */
+  };
+
 static struct option const long_opts[] =
 {
   {"directory", no_argument, NULL, 'd'},
   {"force", no_argument, NULL, 'f'},
-  {"interactive", no_argument, NULL, 'i'},
+  {"interactive", optional_argument, NULL, INTERACTIVE_OPTION},
 
   {"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},
   {"preserve-root", no_argument, NULL, PRESERVE_ROOT},
@@ -97,6 +107,20 @@ static struct option const long_opts[] =
   {NULL, 0, NULL, 0}
 };
 
+static char const *const interactive_args[] =
+{
+  "never", "no", "none",
+  "once",
+  "always", "yes", NULL
+};
+static enum interactive_type const interactive_types[] =
+{
+  interactive_never, interactive_never, interactive_never,
+  interactive_once,
+  interactive_always, interactive_always
+};
+ARGMATCH_VERIFY (interactive_args, interactive_types);
+
 /* Advise the user about invalid usages like "rm -foo" if the file
    "-foo" exists, assuming ARGC and ARGV are as with `main'.  */
 
@@ -132,16 +156,22 @@ usage (int status)
             program_name);
   else
     {
-      char *base = base_name (program_name);
       printf (_("Usage: %s [OPTION]... FILE...\n"), program_name);
       fputs (_("\
 Remove (unlink) the FILE(s).\n\
 \n\
   -f, --force           ignore nonexistent files, never prompt\n\
-  -i, --interactive     prompt before any removal\n\
+  -i                    prompt before every removal\n\
 "), stdout);
       fputs (_("\
-      --no-preserve-root do not treat `/' specially (the default)\n\
+  -I                    prompt once before removing more than three files, 
or\n\
+                          when removing recursively.  Less intrusive than 
-i,\n\
+                          while still giving protection against most 
mistakes\n\
+      --interactive[=WHEN]  prompt according to WHEN: never, once (-I), or\n\
+                          always (-i).  Without WHEN, prompt once\n\
+"), stdout);
+      fputs (_("\
+      --no-preserve-root  do not treat `/' specially (the default)\n\
       --preserve-root   fail to operate recursively on `/'\n\
   -r, -R, --recursive   remove directories and their contents recursively\n\
   -v, --verbose         explain what is being done\n\
@@ -161,7 +191,7 @@ use one of these commands:\n\
 \n\
   %s ./-foo\n\
 "),
-             base, base);
+             program_name, program_name);
       fputs (_("\
 \n\
 Note that if you use rm to remove a file, it is usually possible to recover\n\
@@ -193,6 +223,7 @@ main (int argc, char **argv)
 {
   bool preserve_root = false;
   struct rm_options x;
+  bool prompt_once = false;
   int c;
 
   initialize_main (&argc, &argv);
@@ -205,7 +236,7 @@ main (int argc, char **argv)
 
   rm_option_init (&x);
 
-  while ((c = getopt_long (argc, argv, "dfirvR", long_opts, NULL)) != -1)
+  while ((c = getopt_long (argc, argv, "dfirvIR", long_opts, NULL)) != -1)
     {
       switch (c)
        {
@@ -219,11 +250,19 @@ main (int argc, char **argv)
        case 'f':
          x.interactive = false;
          x.ignore_missing_files = true;
+         prompt_once = false;
          break;
 
        case 'i':
          x.interactive = true;
          x.ignore_missing_files = false;
+         prompt_once = false;
+         break;
+
+       case 'I':
+         x.interactive = false;
+         x.ignore_missing_files = false;
+         prompt_once = true;
          break;
 
        case 'r':
@@ -231,6 +270,36 @@ main (int argc, char **argv)
          x.recursive = true;
          break;
 
+       case INTERACTIVE_OPTION:
+         {
+           int i;
+           if (optarg)
+             i = XARGMATCH ("--interactive", optarg, interactive_args,
+                            interactive_types);
+           else
+             i = interactive_once;
+           switch (i)
+             {
+             case interactive_never:
+               x.interactive = false;
+               prompt_once = false;
+               break;
+
+             case interactive_once:
+               x.interactive = false;
+               x.ignore_missing_files = false;
+               prompt_once = true;
+               break;
+
+             case interactive_always:
+               x.interactive = true;
+               x.ignore_missing_files = false;
+               prompt_once = false;
+               break;
+             }
+           break;
+         }
+
        case NO_PRESERVE_ROOT:
          preserve_root = false;
          break;
@@ -279,6 +348,16 @@ main (int argc, char **argv)
     size_t n_files = argc - optind;
     char const *const *file = (char const *const *) argv + optind;
 
+    if (prompt_once && (x.recursive || 3 < n_files))
+      {
+       fprintf (stderr,
+                (x.recursive
+                 ? _("%s: remove all arguments recursively? ")
+                 : _("%s: remove all arguments? ")),
+                program_name);
+       if (!yesno ())
+         exit (EXIT_SUCCESS);
+      }
     enum RM_status status = rm (n_files, file, &x);
     assert (VALID_STATUS (status));
     exit (status == RM_ERROR ? EXIT_FAILURE : EXIT_SUCCESS);
Index: doc/coreutils.texi
===================================================================
RCS file: /cvsroot/coreutils/coreutils/doc/coreutils.texi,v
retrieving revision 1.297
diff -u -p -r1.297 coreutils.texi
--- doc/coreutils.texi  26 Nov 2005 07:52:43 -0000      1.297
+++ doc/coreutils.texi  3 Dec 2005 20:50:29 -0000
@@ -7271,10 +7271,16 @@ rm address@hidden@dots{} address@hidden@do
 @end example
 
 @cindex prompting, and @command{rm}
-If a file is unwritable, standard input is a terminal, and the @option{-f}
-or @option{--force} option is not given, or the @option{-i} or
address@hidden option @emph{is} given, @command{rm} prompts the user
-for whether to remove the file.
+If the @option{-I} or @option{--interactive=once} option is given,
+and there are more than three files or the @option{-r}, @option{-R},
+or @option{--recursive} are given, then @command{rm} prompts the user
+for whether to proceed with the entire operation.  If the response is
+not affirmitive, the entire command is aborted.
+
+Otherwise, if a file is unwritable, standard input is a terminal, and
+the @option{-f} or @option{--force} option is not given, or the
address@hidden or @option{--interactive=always} option @emph{is} given,
address@hidden prompts the user for whether to remove the file.
 If the response is not affirmative, the file is skipped.
 
 @emph{Warning}: If you use @command{rm} to remove a file, it is usually
@@ -7293,12 +7299,37 @@ Ignore nonexistent files and never promp
 Ignore any previous @option{--interactive} (@option{-i}) option.
 
 @item -i
address@hidden --interactive
 @opindex -i
address@hidden --interactive
 Prompt whether to remove each file.
 If the response is not affirmative, the file is skipped.
 Ignore any previous @option{--force} (@option{-f}) option.
+Equivalent to @option{--interactive=always}.
+
address@hidden -I
address@hidden -I
+Prompt once whether to proceed with the command, if more than three
+files are named or if a recursive removal is requested.  Ignore any
+previous @option{--force} (@option{-f}) option.  Equivalent to
address@hidden
+
address@hidden --interactive address@hidden
address@hidden --interactive
+Specify when to issue an interactive prompt.  @var{when} may be
+omitted, or one of:
address@hidden @bullet
address@hidden never
address@hidden never @r{interactive option}
+- Do not prompt at all.
address@hidden once
address@hidden once @r{interactive option}
+- Prompt once if more than three files are named or if a recursive
+removal is requested.
address@hidden always
address@hidden always @r{interactive option}
+- Prompt for every file being removed.
address@hidden itemize
+Specifying @option{--interactive} and no @var{when} is equivalent to
address@hidden
 
 @itemx --preserve-root
 @opindex --preserve-root

reply via email to

[Prev in Thread] Current Thread [Next in Thread]