-----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 <[EMAIL PROTECTED]> * 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 <[EMAIL PROTECTED]> * coreutils.texi (rm invocation): Document new -I option, and new --interactive behavior. - -- Life is short - so eat dessert first! Eric Blake [EMAIL PROTECTED] -----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 [EMAIL PROTECTED]@dots{} [EMAIL PROTECTED]@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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] or @option{--interactive=always} option @emph{is} given, [EMAIL PROTECTED] 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 [EMAIL PROTECTED] --interactive @opindex -i [EMAIL PROTECTED] --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}. + [EMAIL PROTECTED] -I [EMAIL PROTECTED] -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 [EMAIL PROTECTED] + [EMAIL PROTECTED] --interactive [EMAIL PROTECTED] [EMAIL PROTECTED] --interactive +Specify when to issue an interactive prompt. @var{when} may be +omitted, or one of: [EMAIL PROTECTED] @bullet [EMAIL PROTECTED] never [EMAIL PROTECTED] never @r{interactive option} +- Do not prompt at all. [EMAIL PROTECTED] once [EMAIL PROTECTED] once @r{interactive option} +- Prompt once if more than three files are named or if a recursive +removal is requested. [EMAIL PROTECTED] always [EMAIL PROTECTED] always @r{interactive option} +- Prompt for every file being removed. [EMAIL PROTECTED] itemize +Specifying @option{--interactive} and no @var{when} is equivalent to [EMAIL PROTECTED] @itemx --preserve-root @opindex --preserve-root
_______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils