GNU bug report logs - #15926
RFE: unlink command already uses 'unlink' call; make 'rm' use 'remove' call

Previous Next

Package: coreutils;

Reported by: Linda Walsh <coreutils <at> tlinx.org>

Date: Tue, 19 Nov 2013 11:58:02 UTC

Severity: normal

Tags: notabug, patch

Merged with 15943

Done: Assaf Gordon <assafgordon <at> gmail.com>

Bug is archived. No further changes may be made.

Full log


Message #89 received at 15926 <at> debbugs.gnu.org (full text, mbox):

From: Bernhard Voelker <mail <at> bernhard-voelker.de>
To: Eric Blake <eblake <at> redhat.com>
Cc: 15926 <at> debbugs.gnu.org, Bob Proulx <bob <at> proulx.com>
Subject: Re: bug#15926: RFE: unlink command already uses 'unlink' call; make
 'rm' use 'remove' call
Date: Thu, 21 Nov 2013 17:18:35 +0100
On 11/21/2013 04:06 PM, Eric Blake wrote:
> Hard to say that it is considerable bloat without seeing a patch; we
> already know when the top-level arguments are directories thanks to 'rm -d'.

Here's a draft - not tested more than this:

  $ mkdir -p /tmp/dir /tmp/dir/sub
  $ touch /tmp/dir/file /tmp/dir/sub/other

  $ src/rm -rv --child /tmp/dir
  removed ‘/tmp/dir/file’
  removed ‘/tmp/dir/sub/other’
  removed directory: ‘/tmp/dir/sub’
  src/rm: skipping ‘/tmp/dir’, due to --children-only

  $ src/rm -rv --child /tmp/dir
  src/rm: skipping ‘/tmp/dir’, due to --children-only

  $ src/rm -rv --child /tmp/dir/.
  src/rm: skipping ‘/tmp/dir/.’, due to --children-only

Have a nice day,
Berny

From 03d58cc281c6155d50be9b770bbac7bf73cdaf92 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail <at> bernhard-voelker.de>
Date: Thu, 21 Nov 2013 17:11:27 +0100
Subject: [PATCH] rm: add --children-only option

FIXME
---
 src/mv.c     |  1 +
 src/remove.c | 29 ++++++++++++++++++++++++-----
 src/remove.h |  4 ++++
 src/rm.c     |  9 +++++++++
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/src/mv.c b/src/mv.c
index 1cfcd82..36e70a4 100644
--- a/src/mv.c
+++ b/src/mv.c
@@ -74,6 +74,7 @@ rm_option_init (struct rm_options *x)
 {
   x->ignore_missing_files = false;
   x->remove_empty_directories = true;
+  x->children_only = false;
   x->recursive = true;
   x->one_file_system = false;

diff --git a/src/remove.c b/src/remove.c
index 3d386cf..eb05cb4 100644
--- a/src/remove.c
+++ b/src/remove.c
@@ -439,8 +439,10 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options 
const *x)
         {
           /* POSIX says:
              If the basename of a command line argument is "." or "..",
-             diagnose it and do nothing more with that argument.  */
-          if (dot_or_dotdot (last_component (ent->fts_accpath)))
+             diagnose it and do nothing more with that argument.
+             FIXME: mention --children-only.  */
+          if (! x->children_only
+              && dot_or_dotdot (last_component (ent->fts_accpath)))
             {
               error (0, 0,
                      _("refusing to remove %s or %s directory: 
skipping %s"),
@@ -468,9 +470,17 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options 
const *x)

         if (s == RM_OK && is_empty_directory == T_YES)
           {
-            /* When we know (from prompt when in interactive mode)
-               that this is an empty directory, don't prompt twice.  */
-            s = excise (fts, ent, x, true);
+            if (FTS_ROOTLEVEL == ent->fts_level && x->children_only)
+              {
+                error (0, 0, _("skipping %s, due to --children-only"),
+                       quote (ent->fts_path));
+              }
+            else
+              {
+                /* When we know (from prompt when in interactive mode)
+                   that this is an empty directory, don't prompt twice.  */
+                s = excise (fts, ent, x, true);
+              }
             fts_skip_tree (fts, ent);
           }

@@ -492,6 +502,15 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options 
const *x)
     case FTS_NSOK:		/* e.g., dangling symlink */
     case FTS_DEFAULT:		/* none of the above */
       {
+        if (ent->fts_info == FTS_DP
+            && x->children_only
+            && FTS_ROOTLEVEL == ent->fts_level)
+          {
+            mark_ancestor_dirs (ent);
+            error (0, 0, _("skipping %s, due to --children-only"),
+                   quote (ent->fts_path));
+            return RM_OK;
+          }
         /* With --one-file-system, do not attempt to remove a mount point.
            fts' FTS_XDEV ensures that we don't process any entries under
            the mount point.  */
diff --git a/src/remove.h b/src/remove.h
index 9ac54d4..248a470 100644
--- a/src/remove.h
+++ b/src/remove.h
@@ -52,6 +52,10 @@ struct rm_options
   /* If true, remove empty directories.  */
   bool remove_empty_directories;

+  /* If true (and the -r option is also specified), remove all children
+     of directory arguments, yet retaining the directory itself.  */
+  bool children_only;
+
   /* Pointer to the device and inode numbers of '/', when --recursive
      and preserving '/'.  Otherwise NULL.  */
   struct dev_ino *root_dev_ino;
diff --git a/src/rm.c b/src/rm.c
index 7a51eef..0634855 100644
--- a/src/rm.c
+++ b/src/rm.c
@@ -51,6 +51,7 @@ enum
   ONE_FILE_SYSTEM,
   NO_PRESERVE_ROOT,
   PRESERVE_ROOT,
+  CHILDREN_ONLY,
   PRESUME_INPUT_TTY_OPTION
 };

@@ -78,6 +79,7 @@ static struct option const long_opts[] =

   {"recursive", no_argument, NULL, 'r'},
   {"dir", no_argument, NULL, 'd'},
+  {"children-only", no_argument, NULL, CHILDREN_ONLY},
   {"verbose", no_argument, NULL, 'v'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
@@ -156,6 +158,8 @@ Remove (unlink) the FILE(s).\n\
       --preserve-root   do not remove '/' (default)\n\
   -r, -R, --recursive   remove directories and their contents 
recursively\n\
   -d, --dir             remove empty directories\n\
+      --children-only   remove only children, yet retaining the given\n\
+                          directory arguments\n\
   -v, --verbose         explain what is being done\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
@@ -192,6 +196,7 @@ rm_option_init (struct rm_options *x)
   x->interactive = RMI_SOMETIMES;
   x->one_file_system = false;
   x->remove_empty_directories = false;
+  x->children_only = false;
   x->recursive = false;
   x->root_dev_ino = NULL;
   x->stdin_tty = isatty (STDIN_FILENO);
@@ -296,6 +301,10 @@ main (int argc, char **argv)
           preserve_root = true;
           break;

+        case CHILDREN_ONLY:
+          x.children_only = true;
+          break;
+
         case PRESUME_INPUT_TTY_OPTION:
           x.stdin_tty = true;
           break;
-- 
1.8.4.2





This bug report was last modified 6 years and 225 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.