diff options
author | Krzysztof Goj <krzysztof.goj@gmail.com> | 2012-01-22 01:39:59 +0100 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2012-08-14 18:54:16 +0200 |
commit | fdc2da7165d93c8065365999341173ad2a818833 (patch) | |
tree | 25ef66176016b61abb71b56175b6cdb42fb54ee4 /src | |
parent | 46afefaaa8ea95b5eb63a62792774cd18738234a (diff) | |
download | coreutils-fdc2da7165d93c8065365999341173ad2a818833.tar.xz |
rm: new option --dir (-d) to remove empty directories
Add new option to rm (-d/--dir), which allows removal of
empty directories, while still safely disallowing removal
of non-empty ones.
This improves compatibility with Mac OS X and BSD systems,
which honor the -d option.
* src/remove.c (rm_fts): Remove empty directories when requested.
* src/remove.h (rm_options) [remove_empty_directories]: New member.
* src/rm.c (long_opts, usage, main): Update usage and option parsing.
(rm_option_init): Initialize the new member.
* src/mv.c (rm_option_init): Initialize the new member.
* tests/rm/d-1: New test case - successfully delete empty dir.
* tests/rm/d-2: New test case - refuse to delete nonempty dir.
* tests/Makefile.am (TESTS): Add them.
Diffstat (limited to 'src')
-rw-r--r-- | src/mv.c | 1 | ||||
-rw-r--r-- | src/remove.c | 10 | ||||
-rw-r--r-- | src/remove.h | 3 | ||||
-rw-r--r-- | src/rm.c | 9 |
4 files changed, 19 insertions, 4 deletions
@@ -73,6 +73,7 @@ static void rm_option_init (struct rm_options *x) { x->ignore_missing_files = false; + x->remove_empty_directories = true; x->recursive = true; x->one_file_system = false; diff --git a/src/remove.c b/src/remove.c index 5ebd2ce43..61ba5f372 100644 --- a/src/remove.c +++ b/src/remove.c @@ -414,11 +414,15 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) switch (ent->fts_info) { case FTS_D: /* preorder directory */ - if (! x->recursive) + if (! x->recursive + && !(x->remove_empty_directories + && is_empty_dir (fts->fts_cwd_fd, ent->fts_accpath))) { - /* This is the first (pre-order) encounter with a directory. + /* This is the first (pre-order) encounter with a directory + that we can not delete. Not recursive, so arrange to skip contents. */ - error (0, EISDIR, _("cannot remove %s"), quote (ent->fts_path)); + int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR; + error (0, err, _("cannot remove %s"), quote (ent->fts_path)); mark_ancestor_dirs (ent); fts_skip_tree (fts, ent); return RM_ERROR; diff --git a/src/remove.h b/src/remove.h index 4eab2821f..f994517af 100644 --- a/src/remove.h +++ b/src/remove.h @@ -49,6 +49,9 @@ struct rm_options /* If true, recursively remove directories. */ bool recursive; + /* If true, remove empty directories. */ + bool remove_empty_directories; + /* Pointer to the device and inode numbers of '/', when --recursive and preserving '/'. Otherwise NULL. */ struct dev_ino *root_dev_ino; @@ -77,6 +77,7 @@ static struct option const long_opts[] = {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION}, {"recursive", no_argument, NULL, 'r'}, + {"dir", no_argument, NULL, 'd'}, {"verbose", no_argument, NULL, 'v'}, {GETOPT_HELP_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL}, @@ -154,6 +155,7 @@ Remove (unlink) the FILE(s).\n\ --no-preserve-root do not treat '/' specially\n\ --preserve-root do not remove '/' (default)\n\ -r, -R, --recursive remove directories and their contents recursively\n\ + -d, --dir remove empty directories\n\ -v, --verbose explain what is being done\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); @@ -189,6 +191,7 @@ rm_option_init (struct rm_options *x) x->ignore_missing_files = false; x->interactive = RMI_SOMETIMES; x->one_file_system = false; + x->remove_empty_directories = false; x->recursive = false; x->root_dev_ino = NULL; x->stdin_tty = isatty (STDIN_FILENO); @@ -220,10 +223,14 @@ main (int argc, char **argv) /* Try to disable the ability to unlink a directory. */ priv_set_remove_linkdir (); - while ((c = getopt_long (argc, argv, "firvIR", long_opts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "dfirvIR", long_opts, NULL)) != -1) { switch (c) { + case 'd': + x.remove_empty_directories = true; + break; + case 'f': x.interactive = RMI_NEVER; x.ignore_missing_files = true; |