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::Bubble
should work once the module has been indexed;or clone this repo and issue
zef install <path-to-cloned-repo>
;or clone,
cd
into 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-parent
etc.
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.