]> Sergey Matveev's repositories - bfs.git/blob - README.md
Merge branch 'io-uring'
[bfs.git] / README.md
1 <div align="center">
2
3 <h1>
4 <code>bfs</code>
5 <br clear="all">
6 <a href="https://github.com/tavianator/bfs/releases"><img src="https://img.shields.io/github/v/tag/tavianator/bfs?label=version" alt="Version" align="left"></a>
7 <a href="/LICENSE"><img src="https://img.shields.io/badge/license-0BSD-blue.svg" alt="License" align="left"></a>
8 <a href="https://github.com/tavianator/bfs/actions/workflows/ci.yml"><img src="https://github.com/tavianator/bfs/actions/workflows/ci.yml/badge.svg" alt="CI Status" align="right"></a>
9 <a href="https://codecov.io/gh/tavianator/bfs"><img src="https://img.shields.io/codecov/c/github/tavianator/bfs?token=PpBVuozOVC" alt="Code coverage" align="right"/></a>
10 </h1>
11
12 **[Features]   •   [Installation]   •   [Usage]   •   [Building]   •   [Hacking]   •   [Changelog]**
13
14 [Features]: #features
15 [Installation]: #installation
16 [Usage]: /docs/USAGE.md
17 [Building]: /docs/BUILDING.md
18 [Hacking]: /docs/HACKING.md
19 [Changelog]: /docs/CHANGELOG.md
20
21 <picture>
22   <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-dark.svg">
23   <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-light.svg">
24   <img alt="Screencast" src="https://raw.githubusercontent.com/tavianator/bfs/gh-pages/animation-light.svg">
25 </picture>
26 <p></p>
27
28 </div>
29
30 `bfs` is a variant of the UNIX `find` command that operates [**breadth-first**](https://en.wikipedia.org/wiki/Breadth-first_search) rather than [**depth-first**](https://en.wikipedia.org/wiki/Depth-first_search).
31 It is otherwise compatible with many versions of `find`, including
32
33 <div align="center">
34
35 **[POSIX]   •   [GNU]   •   [FreeBSD]   •   [OpenBSD]   •   [NetBSD]   •   [macOS]**
36
37 [POSIX]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
38 [GNU]: https://www.gnu.org/software/findutils/
39 [FreeBSD]: https://www.freebsd.org/cgi/man.cgi?find(1)
40 [OpenBSD]: https://man.openbsd.org/find.1
41 [NetBSD]: https://man.netbsd.org/find.1
42 [macOS]: https://ss64.com/osx/find.html
43
44 </div>
45
46 If you're not familiar with `find`, the [GNU find manual](https://www.gnu.org/software/findutils/manual/html_mono/find.html) provides a good introduction.
47
48
49 Features
50 --------
51
52 <details>
53 <summary>
54 <code>bfs</code> operates breadth-first, which typically finds the file(s) you're looking for faster.
55 </summary>
56 <p></p>
57
58 Imagine the following directory tree:
59
60 <pre>
61 haystack
62 ├── deep
63 │   └── 1
64 │       └── 2
65 │           └── 3
66 │               └── 4
67 │                   └── ...
68 └── shallow
69     └── <strong>needle</strong>
70 </pre>
71
72 `find` will explore the entire `deep` directory tree before it ever gets to the `shallow` one that contains what you're looking for.
73 On the other hand, `bfs` lists files from shallowest to deepest, so you never have to wait for it to explore an entire unrelated subtree.
74
75 <table>
76 <tbody>
77 <tr><th><code>bfs</code></th><th><code>find</code></th></tr>
78 <tr>
79 <td width="506" valign="top">
80
81 ```console
82 $ bfs haystack
83 haystack
84 haystack/deep
85 haystack/shallow
86 haystack/deep/1
87 haystack/shallow/needle
88 ...
89 ```
90
91 </td>
92 <td width="506" valign="top">
93
94 ```console
95 $ find haystack
96 haystack
97 haystack/deep
98 haystack/deep/1
99 haystack/deep/1/2
100 haystack/deep/1/2/3
101 haystack/deep/1/2/3/4
102 ...
103 haystack/shallow
104 haystack/shallow/needle
105 ```
106
107 </td>
108 </tr>
109 </tbody>
110 </table>
111 </details>
112
113 <details>
114 <summary>
115 <code>bfs</code> tries to be easier to use than <code>find</code>, while remaining compatible.
116 </summary>
117 <p></p>
118
119 For example, `bfs` is less picky about where you put its arguments:
120
121 <table>
122 <tbody>
123 <tr><th><code>bfs</code></th><th><code>find</code></th></tr>
124 <tr>
125 <td width="506">
126
127 ```console
128 $ bfs -L -name 'needle' haystack
129 haystack/needle
130
131 $ bfs haystack -L -name 'needle'
132 haystack/needle
133
134 $ bfs -L haystack -name 'needle'
135 haystack/needle
136 ```
137
138 </td>
139 <td width="506">
140
141 ```console
142 $ find -L -name 'needle' haystack
143 find: paths must precede expression: haystack
144
145 $ find haystack -L -name 'needle'
146 find: unknown predicate `-L'
147
148 $ find -L haystack -name 'needle'
149 haystack/needle
150 ```
151
152 </td>
153 </tr>
154 </tbody>
155 </table>
156 </details>
157
158 <details>
159 <summary>
160 <code>bfs</code> gives helpful errors and warnings.
161 </summary>
162 <p></p>
163
164 For example, `bfs` will detect and suggest corrections for typos:
165
166 ```console
167 $ bfs -nam needle
168 bfs: error: bfs -nam needle
169 bfs: error:     ~~~~
170 bfs: error: Unknown argument; did you mean -name?
171 ```
172
173 `bfs` also includes a powerful static analysis to help catch mistakes:
174
175 ```console
176 $ bfs -print -name 'needle'
177 bfs: warning: bfs -print -name needle
178 bfs: warning:            ~~~~~~~~~~~~
179 bfs: warning: The result of this expression is ignored.
180 ```
181
182 </details>
183
184 <details>
185 <summary>
186 <code>bfs</code> adds some options that make common tasks easier.
187 </summary>
188 <p></p>
189
190 For example, the `-exclude` operator skips over entire subtrees whenever an expression matches.
191 `-exclude` is both more powerful and easier to use than the standard `-prune` action; compare
192
193 <pre>
194 $ bfs -name config <strong>-exclude -name .git</strong>
195 </pre>
196
197 to the equivalent
198
199 <pre>
200 $ find <strong>! \( -name .git -prune \)</strong> -name config
201 </pre>
202
203 As an additional shorthand, `-nohidden` skips over all hidden files and directories.
204 See the [usage documentation](/docs/USAGE.md#extensions) for more about the extensions provided by `bfs`.
205 </details>
206
207
208 Installation
209 ------------
210
211 <details open>
212 <summary>
213 <code>bfs</code> may already be packaged for your operating system.
214 </summary>
215 <p></p>
216
217 <table>
218 <tbody>
219 <tr><th>Linux</th><th>macOS</th></tr>
220
221 <tr>
222 <td width="506" valign="top" rowspan="3">
223
224 <pre>
225 <strong><a href="https://pkgs.alpinelinux.org/packages?name=bfs">Alpine Linux</a></strong>
226 # apk add bfs
227
228 <strong><a href="https://archlinux.org/packages/extra/x86_64/bfs/">Arch Linux</a></strong>
229 # pacman -S bfs
230
231 <strong><a href="https://packages.debian.org/sid/bfs">Debian</a>/<a href="https://packages.ubuntu.com/kinetic/bfs">Ubuntu</a></strong>
232 # apt install bfs
233
234 <strong><a href="https://src.fedoraproject.org/rpms/bfs">Fedora Linux</a></strong>
235 # dnf install bfs
236
237 <strong><a href="https://packages.guix.gnu.org/packages/bfs/">GNU Guix</a></strong>
238 # guix install bfs
239
240 <strong><a href="https://search.nixos.org/packages?channel=unstable&show=bfs&from=0&size=1&sort=relevance&type=packages&query=bfs">NixOS</a></strong>
241 # nix-env -i bfs
242
243 <strong><a href="https://voidlinux.org/packages/?arch=x86_64&q=bfs">Void Linux</a></strong>
244 # xbps-install -S bfs
245 </pre>
246
247 </td>
248 <td width="506" valign="top">
249
250 <pre>
251 <strong><a href="https://formulae.brew.sh/formula/bfs">Homebrew</a></strong>
252 $ brew install bfs
253
254 <strong><a href="https://ports.macports.org/port/bfs/">MacPorts</a></strong>
255 # port install bfs
256 </pre>
257
258 </td>
259 </tr>
260 <tr><th height="1">BSD</th></tr>
261 <tr>
262 <td width="506" valign="top">
263
264 <pre>
265 <strong><a href="https://www.freshports.org/sysutils/bfs">FreeBSD</a></strong>
266 # pkg install bfs
267
268 <strong><a href="https://openports.pl/path/sysutils/bfs">OpenBSD</a></strong>
269 # pkg_add bfs
270 </pre>
271
272 </td>
273 </tr>
274 </tbody>
275 </table>
276 </details>
277
278 <details>
279 <summary>
280 To build <code>bfs</code> from source, you may need to install some dependencies.
281 </summary>
282 <p></p>
283
284 The only absolute requirements for building `bfs` are a C compiler, [GNU make](https://www.gnu.org/software/make/), and [Bash](https://www.gnu.org/software/bash/).
285 These are installed by default on many systems, and easy to install on most others.
286 Refer to your operating system's documentation on building software.
287
288 `bfs` also depends on some system libraries for some of its features.
289 Here's how to install them on some common platforms:
290
291 <pre>
292 <strong>Alpine Linux</strong>
293 # apk add acl{,-dev} attr{,-dev} libcap{,-dev} liburing-dev oniguruma-dev
294
295 <strong>Arch Linux</strong>
296 # pacman -S acl attr libcap liburing oniguruma
297
298 <strong>Debian/Ubuntu</strong>
299 # apt install acl libacl1-dev attr libattr1-dev libcap2-bin libcap-dev liburing-dev libonig-dev
300
301 <strong>Fedora</strong>
302 # dnf install acl libacl-devel libattr-devel libcap-devel liburing-devel oniguruma-devel
303
304 <strong>NixOS</strong>
305 # nix-env -i acl attr libcap liburing oniguruma
306
307 <strong>Void Linux</strong>
308 # xbps-install -S acl-{devel,progs} attr-{devel,progs} libcap-{devel,progs} liburing-devel oniguruma-devel
309
310 <strong>Homebrew</strong>
311 $ brew install oniguruma
312
313 <strong>MacPorts</strong>
314 # port install oniguruma6
315
316 <strong>FreeBSD</strong>
317 # pkg install oniguruma
318 </pre>
319
320 These dependencies are technically optional, though strongly recommended.
321 See the [build documentation](/docs/BUILDING.md#dependencies) for how to disable them.
322 </details>
323
324 <details>
325 <summary>
326 Once you have the dependencies, you can build <code>bfs</code>.
327 </summary>
328 <p></p>
329
330 Download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs).
331 Then run
332
333     $ make
334
335 This will build the `./bin/bfs` binary.
336 Run the test suite to make sure it works correctly:
337
338     $ make check
339
340 If you're interested in speed, you may want to build the release version instead:
341
342     $ make release
343
344 Finally, if you want to install it globally, run
345
346     # make install
347
348 </details>