---
tags:
  - shell
---

# `find`

`find` can be used both to locate files and run operations on the files it
finds.

## Main syntax

### No options

Without options specified, `find` alone will return a recursive index of all the
files in the directory from which it is run.

### Sub-directory

If we pass a directory to `find` it will repeat the above process but
specifically for that directory.

```bash
$ find i3
i3
i3/config
```

### Filters

We can specify flags as filters (known as 'tests' within the program).

#### Type

Filter by type: file or directory

```
$ find -type d # return dirs only
$ find -type f # return files only
```

Within a specified directory:

```bash
$ find i3 -type f
```

#### Filename

This is the most frequent use case: filter files by name with globbing.

```bash
$ find -name "config"
./.git/config
./i3/config
```

```bash
$ find -name "*.js"
```

The same, but case insensitive: `iname`

```bash
$ find -iname "*.JS"
```

#### Path

As above but this time includes directory names in the match. `ipath` is the
case-insensitive version.

```bash
$ find -path "utils*"
utils.js
utils/do-something.js
```

### Operators

We can combine `find` commands by using logical operators: `-and`, `-or`,
`-not`. For example:

```bash
$ find -not -name "*.js" -type f
./app/index.html
./app/style.css
./dist/index.html
./dist/style.c
```

Applied to a directory:

```bash
find . -type -f -not -path "./.git/"
```

## Run programs against results

Using the `exec` keyword we can run a program against the files that are
returned from `find`.

In this syntax we use `{}` as a placeholder for the path of the file that is
matched. We use `;` (escaped) to indicate the end of the operation.

### Examples

This script deletes the files that match the filter criteria:

```bash
$ find -name "*.js" -exec rm {} \;
```

This script finds all the files with the substring 'config' in their name and
writes their file size to a file.

```bash
find -name '*config*' -exec wc -c {} \; > config-sizes
```
