1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
Using `bfs`
===========
`bfs` has the same command line syntax as `find`, and almost any `find` command that works with a major `find` implementation will also work with `bfs`.
When invoked with no arguments, `bfs` will list everything under the current directory recursively, breadth-first:
```console
$ bfs
.
./LICENSE
./Makefile
./README.md
./completions
./docs
./src
./tests
./completions/bfs.bash
./completions/bfs.zsh
./docs/BUILDING.md
./docs/CHANGELOG.md
./docs/CONTRIBUTING.md
./docs/USAGE.md
./docs/bfs.1
...
```
Paths
-----
Arguments that don't begin with `-` are treated as paths to search.
If one or more paths are specified, they are used instead of the current directory:
```console
$ bfs /usr/bin /usr/lib
/usr/bin
/usr/lib
/usr/bin/bfs
...
/usr/lib/libc.so
...
```
Expressions
-----------
Arguments that start with `-` form an *expression* which `bfs` evaluates to filter the matched files, and to do things with the files that match.
The most common expression is probably `-name`, which matches filenames against a glob pattern:
```console
$ bfs -name '*.md'
./README.md
./docs/BUILDING.md
./docs/CHANGELOG.md
./docs/CONTRIBUTING.md
./docs/USAGE.md
```
### Operators
When you put multiple expressions next to each other, both of them must match:
```console
$ bfs -name '*.md' -name '*ING*'
./docs/BUILDING.md
./docs/CONTRIBUTING.md
```
This works because the expressions are implicitly combined with *logical and*.
You could be explicit by writing
```console
$ bfs -name '*.md' -and -name '*ING'`
```
There are other operators like `-or`:
```console
$ bfs -name '*.md' -or -name 'bfs.*'
./README.md
./completions/bfs.bash
./completions/bfs.fish
./completions/bfs.zsh
./docs/BUILDING.md
./docs/CHANGELOG.md
./docs/CONTRIBUTING.md
./docs/USAGE.md
./docs/bfs.1
```
and `-not`:
```console
$ bfs -name '*.md' -and -not -name '*ING*'
./README.md
./docs/CHANGELOG.md
./docs/USAGE.md
```
### Actions
Every `bfs` expression returns either `true` or `false`.
For expressions like `-name`, that's all they do.
But some expressions, called *actions*, have other side effects.
If no actions are included in the expression, `bfs` adds the `-print` action automatically, which is why the above examples actually print any output.
The default `-print` is suppressed if any actions are given explicitly.
Available actions include printing with alternate formats (`-ls`, `-printf`, etc.), executing commands (`-exec`, `-execdir`, etc.), deleting files (`-delete`), and stopping the search (`-quit`, `-exit`).
Extensions
----------
`bfs` implements a few extensions not found in other `find` implementations.
### `-exclude`
The `-exclude` operator skips an entire subtree whenever an expression matches.
For example, `-exclude -name .git` will exclude any files or directories named `.git` from the search results.
`-exclude` is easier to use than the standard `-prune` action; compare
bfs -name config -exclude -name .git
to the equivalent
find ! \( -name .git -prune \) -name config
Unlike `-prune`, `-exclude` even works in combination with `-depth`/`-delete`.
---
### `-limit`
The `-limit N` action makes `bfs` quit once it gets evaluated `N` times.
Placing it after an action like `-print` limits the number of results that get printed, for example:
```console
$ bfs -s -type f -name '*.txt'
./1.txt
./2.txt
./3.txt
./4.txt
$ bfs -s -type f -name '*.txt' -print -limit 2
./1.txt
./2.txt
```
This is similar to
```console
$ bfs -s -type f -name '*.txt' | head -n2
```
but more powerful because you can apply separate limits to different expressions:
```console
$ bfs \( -name '*.txt' -print -limit 3 -o -name '*.log' -print -limit 4 \) -limit 5
[At most 3 .txt files, at most 4 .log files, and at most 5 in total]
```
and more efficient because it will quit immediately.
When piping to `head`, `bfs` will only quit *after* it tries to output too many results.
---
### `-hidden`/`-nohidden`
`-hidden` matches "hidden" files (dotfiles).
`bfs -hidden` is effectively shorthand for
find \( -name '.*' -not -name . -not -name .. \)
`-nohidden` is equivalent to `-exclude -hidden`.
---
### `-unique`
This option ensures that `bfs` only visits each file once, even if it's reachable through multiple hard or symbolic links.
It's particularly useful when following symbolic links (`-L`).
---
### `-color`/`-nocolor`
When printing to a terminal, `bfs` automatically colors paths like GNU `ls`, according to the `LS_COLORS` environment variable.
The `-color` and `-nocolor` options override the automatic behavior, which may be handy when you want to preserve colors through a pipe:
bfs -color | less -R
If the [`NO_COLOR`](https://no-color.org/) environment variable is set, colors will be disabled by default.
|