# Find Command Builder

> Build a GNU find command with filters for name, path, size, time, owner and permissions — and see what every flag does. Nothing is executed.

Canonical: https://host-tools.com/tools/find-command-builder/

---

## What this tool does

It writes a GNU `find` command for you. You choose the starting path and the filters — type,
name, path, size, times, owner, group, permissions, depth — and it produces the command plus an
explanation of every part it added. Nothing is executed: the output is text you copy.

## -name and -path are not the same thing

`-name` matches the **file name only**. `-path` matches the **whole path**, which is what you want
when the interesting part is a directory in the middle:

```
find /srv -name '*.log'      # any file ending in .log, anywhere
find /srv -path '*/cache/*'  # anything whose path goes through a cache directory
```

A frequent mistake is trying to put a slash inside `-name`: `-name 'src/*.js'` never matches,
because `-name` only ever sees the file name. Use `-path` for that.

## -mtime and -atime are in days

`-mtime -7` means "modified less than 7 days ago". The sign is the part people get wrong:

| Expression | Meaning |
| --- | --- |
| `-mtime -7` | modified within the last 7 days |
| `-mtime +7` | not modified for more than 7 days |
| `-atime +30` | not accessed for more than 30 days |

`-atime` is useful for finding cold data, but be aware that many systems mount filesystems with
`relatime`, which does not update access times on every read. Treat it as a hint, not a fact.

## -size units

`-size +100M` is more than 100 mebibytes. The units are `c` (bytes), `k`, `M` and `G` — and they
are binary, so `M` is 1,048,576 bytes, not 1,000,000. That is why `du` and this tool can disagree
slightly with a file manager that shows decimal megabytes.

## Running a command on each result: -exec

`-exec` runs a program once per match. The `{}` is replaced by the path and the escaped `\;` closes
the command:

```
find /data -name '*.gz' -exec gzip -d {} \;
```

For many files it is usually faster to let find batch them, but `-exec` is the portable answer and
the one that is easy to read.

## -print0 and why paths with spaces break scripts

By default `find` separates results with a newline, so a path containing a newline or a space is
ambiguous when another program reads the output. `-print0` separates results with a NUL byte, and
commands that accept it (`xargs -0`, `while read -d ''`) then handle any path correctly. If you are
feeding the output to another command, use `-print0`.

## -delete is not like rm

`find … -delete` deletes every match immediately: no confirmation, no trash, no undo. Before using
it, run exactly the same command with `-print` and read the list. The builder hides the command
until you confirm this, and it is worth taking seriously — a missing `-name` filter turns a cleanup
into a disaster.

## Real examples

Clean up logs older than a month:

```
find /var/log -type f -name '*.gz' -mtime +30 -print
```

Find large files that are eating the disk:

```
find / -xdev -type f -size +500M -print
```

Find world-writable files, a classic security check:

```
find /var/www -type f -perm -002 -print
```

To copy the results somewhere else, the [rsync command builder](/tools/rsync-command-builder/) pairs
naturally with this one.
