bug-coreutils
[Top][All Lists]
Advanced

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

bug#15926: RFE: unlink command already uses 'unlink' call; make 'rm' use


From: Bernhard Voelker
Subject: bug#15926: RFE: unlink command already uses 'unlink' call; make 'rm' use 'remove' call
Date: Thu, 21 Nov 2013 17:18:35 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0

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 <address@hidden>
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






reply via email to

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