On 23 Aug 2007, at 14:59, Eric Blake wrote:
Bruno also had the idea of letting -delete operate
without -depth, by letting -delete swap the traversal of that subtree to
depth-first while the rest of the traversal is breadth-first prior to
encountering the -delete action.

Actually, not quite. My proposal amounted to exactly the following:

--- findutils-4.3.8/find/parser.c 2007-06-09 14:12:06.000000000 +0200
+++ findutils-mod/find/parser.c 2007-08-24 12:08:07.000000000 +0200
@@ -724,7 +724,7 @@
   our_pred = insert_primary (entry);
   our_pred->side_effects = our_pred->no_default_print = true;
-  /* -delete implies -depth */
-  options.do_dir_first = false;

   /* We do not need stat information because we check for the case
    * (errno==EISDIR) in pred_delete.

The idea is to have a very straightforward -delete: the action will try to delete the nodes in order, the traversal is not modified in any way. The main benefit over other proposals is that -delete can be combined with normal traversal (and thus with pruning). For example, consider:

$ ../findutils-mod/find/find
.
./aa
./aa/.svn
./aa/.svn/foo
./aa/foo
./bb
./bb/foo
./.svn
./.svn/foo
$ ../findutils-mod/find/find -not "(" -name .svn -prune ")" -name foo -delete
$ ../findutils-mod/find/find
.
./aa
./aa/.svn
./aa/.svn/foo
./bb
./.svn
./.svn/foo

The user will have to make sure that nodes can actually be deleted during the traversal, otherwise he will receive an error. When deleting directories, this means that the directory must be empty. If he wants to delete an entire directory tree as a part of one and the same traversal, he will need to use -depth, but at least he will knowingly change the traversal order then.

Also, after deleting a directory in a normal traversal, find should not try to visit this directory anymore, because it's gone. The user could accomplish this by including a -prune after the -delete, or find could do it automatically, with a change like this:

--- findutils-4.3.8/find/pred.c 2007-06-09 14:12:35.000000000 +0200
+++ findutils-mod/find/pred.c   2007-08-26 19:30:45.000000000 +0200
@@ -392,6 +392,8 @@
        flags |= AT_REMOVEDIR;
       if (perform_delete(flags))
        {
+         if (options.do_dir_first == true && (flags & AT_REMOVEDIR))
+         state.stop_at_current_level = true;
          return true;
        }
       else
@@ -403,7 +405,11 @@
/* unlink() operation failed because we should have done rmdir(). */
                  flags |= AT_REMOVEDIR;
                  if (perform_delete(flags))
+                 {
+ if (options.do_dir_first == true && (flags & AT_REMOVEDIR))
+                   state.stop_at_current_level = true;
                    return true;
+                 }
                }
            }
        }

As such it is possible to -delete empty directories in a normal traversal. For example, consider the following to clean empty subdirectories in a tree:

$ ../findutils-mod/find/find
.
./aa
./aa/foo
./bb
./cc
$ ../findutils-mod/find/find -type d
.
./aa
./aa/foo
./cc
$ ../findutils-mod/find/find -type d -empty -delete
$ ../findutils-mod/find/find
.
./aa
./bb


Regards,
Bruno De Fraine


Reply via email to