bug#15926: RFE: unlink command already uses 'unlink' call; make 'rm' use (original) (raw)


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


From: Jim Meyering
Subject: bug#15926: RFE: unlink command already uses 'unlink' call; make 'rm' use 'remove' call
Date: Thu, 21 Nov 2013 09:02:07 -0800

On Thu, Nov 21, 2013 at 8:18 AM, Bernhard Voelker <address@hidden> wrote:

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 @@ rmoptioninit (struct rmoptions *x) { x->ignoremissingfiles = false; x->removeemptydirectories = true; + x->childrenonly = false; x->recursive = true; x->onefilesystem = 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 @@ rmfts (FTS *fts, FTSENT *ent, struct rmoptions const *x) {

/* POSIX says: If the basename of a command line argument is "." or "..", - diagnose it and do nothing more with that argument. */ - if (dotordotdot (lastcomponent (ent->ftsaccpath))) + diagnose it and do nothing more with that argument. + FIXME: mention --children-only. */ + if (! x->childrenonly + && dotordotdot (lastcomponent (ent->ftsaccpath))) { error (0, 0,

("refusing to remove %s or %s directory: skipping %s"), @@ -468,9 +470,17 @@ rmfts (FTS *fts, FTSENT *ent, struct rmoptions const *x)

if (s == RMOK && isemptydirectory == TYES) { - /* 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 (FTSROOTLEVEL == ent->ftslevel && x->childrenonly) + { + error (0, 0, ("skipping %s, due to --children-only"), + quote (ent->ftspath)); + } + 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); + } ftsskiptree (fts, ent); }

@@ -492,6 +502,15 @@ rmfts (FTS *fts, FTSENT *ent, struct rmoptions const *x) case FTSNSOK: /* e.g., dangling symlink */ case FTSDEFAULT: /* none of the above */ { + if (ent->ftsinfo == FTSDP + && x->childrenonly + && FTSROOTLEVEL == ent->ftslevel) + { + markancestordirs (ent); + error (0, 0, ("skipping %s, due to --children-only"), + quote (ent->ftspath)); + return RMOK; + } /* With --one-file-system, do not attempt to remove a mount point. fts' FTSXDEV 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 rmoptions /* If true, remove empty directories. */ bool removeemptydirectories;

+ /* If true (and the -r option is also specified), remove all children + of directory arguments, yet retaining the directory itself. */ + bool childrenonly; + /* Pointer to the device and inode numbers of '/', when --recursive and preserving '/'. Otherwise NULL. */ struct devino *rootdevino; 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 ONEFILESYSTEM, NOPRESERVEROOT, PRESERVEROOT, + CHILDRENONLY, PRESUMEINPUTTTYOPTION };

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

{"recursive", noargument, NULL, 'r'}, {"dir", noargument, NULL, 'd'}, + {"children-only", noargument, NULL, CHILDRENONLY}, {"verbose", noargument, NULL, 'v'}, {GETOPTHELPOPTIONDECL}, {GETOPTVERSIONOPTIONDECL}, _@@ -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_ ...

Thanks for the quick work.

What do you think about saying something simple yet imprecise in --help, like "when recursive, suppress removal of any directory named on the command line" with the caveat that the texinfo doc would add precision: but a command-line-specified directory may still end up being removed when it is also a subdirectory of another command line argument.