[Top][All Lists]
[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