summaryrefslogtreecommitdiffstats
path: root/README.md
blob: 45aab8927347ffc92eeda823426daa7bbb78d582 (plain)
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
`bfs`
=====

[![License](http://img.shields.io/badge/license-0BSD-blue.svg)](https://github.com/tavianator/bfs/blob/master/COPYING)
[![LOC](https://tokei.rs/b1/github/tavianator/bfs?category=code)](https://github.com/Aaronepower/tokei)
[![Build Status](https://api.travis-ci.org/tavianator/bfs.svg?branch=master)](https://travis-ci.org/tavianator/bfs)

Breadth-first search for your files.

`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).
It is otherwise intended to be compatible with many versions of `find`, including

- [POSIX `find`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html)
- [GNU `find`](https://www.gnu.org/software/findutils/)
- {[Free](https://www.freebsd.org/cgi/man.cgi?find(1)),[Open](https://man.openbsd.org/find.1),[Net](http://netbsd.gw.com/cgi-bin/man-cgi?find+1+NetBSD-current)}BSD `find`
- [macOS `find`](https://ss64.com/osx/find.html)

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.


Breadth vs. depth
-----------------

The advantage of breadth-first over depth first search is that it usually finds the file(s) you're looking for faster.
Imagine the following directory tree:

<pre>
haystack
├── deep
│   └── 1
│       └── 2
│           └── 3
│               └── 4
│                   └── ...
└── shallow
    └── <strong>needle</strong>
</pre>

`find` will explore the entire `deep` directory tree before it ever gets to the `shallow` one that contains what you're looking for.

<pre>
$ <strong>find</strong> haystack
haystack
haystack/deep
haystack/deep/1
haystack/deep/1/2
haystack/deep/1/2/3
haystack/deep/1/2/3/4
...
haystack/shallow
<strong>haystack/shallow/needle</strong>
</pre>

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.

<pre>
$ <strong>bfs</strong> haystack
haystack
haystack/deep
haystack/shallow
haystack/deep/1
<strong>haystack/shallow/needle</strong>
haystack/deep/1/2
haystack/deep/1/2/3
haystack/deep/1/2/3/4
...
</pre>


Easy
----

`bfs` tries to be easier to use than `find`, while remaining compatible.
For example, `bfs` is less picky about where you put its arguments:

<pre>
$ <strong>find</strong> -L -name 'needle' <em>haystack</em>
find: paths must precede expression: haystack
$ <strong>bfs</strong> -L -name 'needle' <em>haystack</em>
<strong>haystack/needle</strong>

$ <strong>find</strong> <em>haystack</em> -L -name 'needle'
find: unknown predicate `-L'
$ <strong>bfs</strong> <em>haystack</em> -L -name 'needle'
<strong>haystack/needle</strong>

$ <strong>find</strong> -L <em>haystack</em> -name 'needle'
<strong>haystack/needle</strong>
$ <strong>bfs</strong> -L <em>haystack</em> -name 'needle'
<strong>haystack/needle</strong>
</pre>

`bfs` also adds some extra options that make some common tasks easier.
Compare `bfs -nohidden` to

    find -name '.?*' -prune -o -print


Pretty
------

When `bfs` detects that its output is a terminal, it automatically colors its output with the same colors `ls` uses.
This makes it easier to identify relevant files at a glance.

<img src="https://tavianator.github.io/bfs/screenshot.svg" alt="Screenshot" width="100%" />


Try it!
-------

To get `bfs`, download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs).
Then run

    $ make

This will build the `bfs` binary in the current directory.
You can test it out:

    $ ./bfs -nohidden

If you're interested in speed, you may want to build the release version instead:

    $ make clean
    $ make release

Finally, if you want to install it globally, run

    $ sudo make install

Alternatively, `bfs` may already be packaged for your distribution of choice:

[![Packaging status](https://repology.org/badge/vertical-allrepos/bfs.svg)](https://repology.org/metapackage/bfs)

For example:

    # apt install bfs                  # Debian/Ubuntu
    # brew install tavianator/tap/bfs  # macOS Homebrew