I am impressed by the sheer amount of functionality offered by the
Unix find command, but remain unable to remember how to use it
for anything other than the basics; otherwise I hit Google.
I don't have a very good memory for flags, but I do remember
expressions. findr is given exactly two arguments; the base directory
and a filter expression:
$ findr . 'path.ext=="rs" && path.size > 1kb'
$ findr . 'path.is_file && date.before("1 jan")'
$ findr . 'path.ext=="md" and date.after("last tuesday")'
The filter expression is passed path, date and mode and fairly arbitrary
expressions are supported, thanks to the very capable little embedded
language rhai. As a little
convenience, "and", "or" and "not" are understood, since these are
easier to type in a hurry.
path has the following fields:
is_file is this path a file?is_dir is this path a directory?is_exec is this file executable?is_write is this path writeable?size size of file entry in bytesext extension of file pathfile_name file name part of pathThere's also a matches method (e.g. path.matches("*/readme.*")).
date has the following methods:
before(datestr) all files modified before this dateafter(datestr) all files modified after this datebetween(datestr,datestr) all files modified between these dateson(datestr) all files modified on this daymode is just the usual Unix permission bits - expressions may
contain octal constants in Rust notation (e.g. 0o755)
Numbers may have a size prefix (kb,mb,gb - not case-sensitive) and date strings are interpreted by chrono-english.
Currently, findr ignores hidden directories and files excluded by .gitignore.
It has not been entirely possible to do without flags!
``` ~$ findr -h findr: find files and filter with expressions
-n, --no-hidden look at hidden files and follow hidden dirs -g, --no-gitignore do not respect .gitignore -m, --manual show more detailed help about findr
```
By default, it speaks British English dates (i.e. not "9/11"),
unless the environment variable FINDR_US is defined.
Respecting .gitignore is something that makes your life easier if you are not particularly interested
in build artifacts. It is particularly useful in Rust projects because incremental compilation
generates a lot of intermediate build artifacts.
With findr, I can now finally answer the question "What the f*k did I do on Tuesday?":
~$ findr . 'date.on("last tues")'
./rust/repos/findr/src/errors.rs
./rust/scratch
./rust/scratch/over/test.over
./rust/scratch/over/type1.over
./rust/scratch/over/over.rs
./rust/scratch/over/empty.over
./rust/scratch/over/tuple.over
./rust/scratch/over/strs.over
./rust/scratch/over/main.over
./rust/scratch/over/id.over
./rust/scratch/over/numbers.over
./rust/scratch/over/strings.over
./rust/scratch/over/map.over
./rust/scratch/over/str.over
./rust/scanlex/src
./rust/scanlex/src/lib.rs
With the -g flag (ignore .gitignore) there are 538 files changed on that day!
To illustrate my point about flag madness, the equivalent of findr . 'path.ext="rs"' is:
find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*.rs' -print
(I had to look that one up)