Bubble
File::Directory::Bubble
A file-removal tool that
optionally bubbles deletion up the directory tree until it hits a non-empty directory;
allows for dry runs, only showing you what *would* be deleted.
Installation
With zef:
just running
zef install File::Directory::Bubbleshould work once the module has been indexed;or clone this repo and issue
zef install <path-to-cloned-repo>;or clone,
cdinto the repo, andzef install ..
Usage
The module provides the executable bin/bbrm for access to (what I believe would be) the most common functionality.
First, you can run bbrm --help for a quick breakdown of the usage. For the examples, I will assume access to the tree utility in order to visualize the directory structure that bbrm is meant to alter.
Throughout, assume you're in a directory with the following structure:
$ tree .
.
āāā a
āĀ Ā āāā b
āĀ Ā āĀ Ā āāā c
āĀ Ā āāā b1
āĀ Ā āĀ Ā āāā c
āĀ Ā āĀ Ā āāā d
āĀ Ā āāā b2
āĀ Ā āāā c
āĀ Ā āāā d
āāā foo.txt
9 directories, 1 file
I will run the bbrm command with the --dry option, so it only shows us what it would remove.
$ bbrm a/b* --dry
Would remove:
<fully-expanded path>/a/b/c
<fully-expanded path>/a/b
<fully-expanded path>/a/b1/c/d
<fully-expanded path>/a/b1/c
<fully-expanded path>/a/b1
<fully-expanded path>/a/b2/c/d
<fully-expanded path>/a/b2/c
<fully-expanded path>/a/b2
As expected, that would remove everything under the directories ./a/b*. On the other hand, the --up flag would also remove the ./a directory, because it would become empty upon removing the other ones:
$ bbrm a/b* --dry --up
Would remove:
<fully-expanded path>/a/b2/c/d
<fully-expanded path>/a/b2/c
<fully-expanded path>/a/b2
<fully-expanded path>/a/b1/c/d
<fully-expanded path>/a/b1/c
<fully-expanded path>/a/b1
<fully-expanded path>/a/b/c
<fully-expanded path>/a/b
<fully-expanded path>/a
In fact, the same would happen if you were to first remove everything at lower levels: empty-directory deletion would still bubble up.
$ bbrm a/b*/c --dry --up
Would remove:
<fully-expanded path>/a/b2/c/d
<fully-expanded path>/a/b2/c
<fully-expanded path>/a/b2
<fully-expanded path>/a/b1/c/d
<fully-expanded path>/a/b1/c
<fully-expanded path>/a/b1
<fully-expanded path>/a/b/c
<fully-expanded path>/a/b
<fully-expanded path>/a
Though again, that only happens with the --up flag. Without it you're only deleting down the directory tree.
$ bbrm a/b*/c --dry
Would remove:
<fully-expanded path>/a/b/c
<fully-expanded path>/a/b1/c/d
<fully-expanded path>/a/b1/c
<fully-expanded path>/a/b2/c/d
<fully-expanded path>/a/b2/c
Other modules in the Raku ecosystem
There's of course File::Directory::Tree, but because it deletes files/directories recursively using unlink and rmdir, it's not easy to build a --dry option on top of it:
If you're doing a dry run you're not actually emptying directories, so rmdir doesn't know what it would remove if you were..
Module functions
The library lib/File/Directory/Bubble.rakumod exports a number of functions, some of which are used by the bbrm utility discussed above.
A summary follows.
Starting with the $file you pass in, it builds the increasingly longer lists of ancestors, as in
$file, parent$file, parent, parent-of-parentetc.
The predicate &cond is called on these lists, so there's quite a bit of generality built into the kinds of conditions you can check for.
The iteration stops when &cond first returns false, giving you back the last list of parents before that happened.
This is a utility function, for use with &bbUpWith above to produce &bbUpEmpty below.
This function allows the bbrm script to list what it would remove upon passing the --up flag, even during a --dry run.
You can presumably build your own more complicated examples using the more general callback-driven &bbUpWith above.