How the find Command works on Linux
Tags: bash, linux, codenewbie, beginners
Published: 2022-03-31 12:48:36

The find command on Linux and Unix like systems (i.e. MacOS) is used to find files and directories in a specific directory. It is one of the most useful commands at your disposal when trying to find and process multiple files. It's also really useful during file audits.

The syntax for find is shown below, where `[OPTIONS]` are optional settings, `[LOCATION]` is the location you want to find something within, and `[SEARCH TERM]` is the file name or directory name you want to find.

```
find [OPTIONS] [LOCATION] [SEARCH TERM]
```

## How to use the find command on Linux and MacOS
The most basic form of the find command looks like this:

```
find ./test *.txt
```

The above command will find any file ending in `.txt`, i.e. `*.txt` within the `./test` folder. This will return a list of all matching files.

### Handling Symbolic Links
Some folders may contain symbolic links that link to another part of your file system. As such, you might unknowingly search a much larger set of folders, if symbolic links do exist. As such, there are a number of options that control what happens when find comes across a symbolic link:

- `-P` - when used, symbolic links are never followed.
- `-L` - when used, symbolic links are always followed.
- `-H` - when used, symbolic links are only followed if mentioned somewhere on the command line, i.e. if you search for link, and there is a symbolic link called link, find will return link along with anything found when following that symbolic link.

Any of these options can be used as shown below:

```
find -P ./test *.txt
```

## Searching file by type
Since there are many different types of files and directories, it is not always useful to just search for a specific string. If we want to mention the type of file or directory we are looking for, we can specify with the -type option. To remove ambiguity, we also add the -name option before our search string. You can also just remove the search string entirely, and search for a particular file type.

Below, we search for everything with type f, which defines a regular file.

```
find ./test -type f -name "*.txt"
```

A full list of all types can be found below:

- `b` - block devices
- `c` - character devices
- `d` - directory
- `p` - named pipe (FIFO)
- `f` - regular file
- `l` - symbolic link - never used if we use the symbolic link -L option.
- `s` - socket

## Searching by size
We can search by size using the -size option. For example we want to find all files of size 10MB, we use 10M:

```
find ./test -size 10M
```

This is not particularly useful, so if we want to find files below or above a certain size, we add - and + respectively. For example, the below will find all files smaller than 10MB.

```
find ./test -size -10M
```

As the sizes aren't normal units i.e. mb, gb, kb, the full list of units can be found below:

- `b` - 512-byte blocks (default).
- `c` - just bytes.
- `w` - two-byte words.
- `k` - Kilobytes.
- `M` - Megabytes.
- `G` - Gigabytes.

## Find by Owner or Group
Using the `-group` or `-user` options, we can also find a directory or file by who owns it, or which group it belongs to. For example, the below code finds all files in the ./test directory where the owner is someOwner:

```
find ./test -user someOwner
```

Similarly, we can find by group like so:

```
find ./test -group someGroup
```

## Find by Permissions
Using `-perm`, we can find all files with a particular permission combination. The below will find all files in the ./test directory with a permission of 0755. If you want to learn more about permissions, read our article on chmod.

```
find ./test -perm 0755
```

## Limiting find Command Depth
Since the find command is recursive, it can sometimes return quite a lot of results. If you want to limit the number of levels, then use the `-maxdepth` option. Similarly, you can use `-mindepth` to define a minimum depth to go to, before results start to be returned.

```
find . -name "*.txt" -maxdepth 2
```

And here is an example with both `-mindepth` and `-maxdepth`, which only returns files within a folder within ./test.

```
find . -name "*.txt" -maxdepth 2 -mindepth 2
```

## Finding Files by Last Accessed/Modified Time
There are a number of different ways to find files based on their last access or modify time. For example, the below command will only find files `*.txt` in the folder `./test` which were last accessed within the last 5 minutes:

```
find . -name "*.txt" -amin 5
```

Here, `-amin` refers to how many minutes ago the file should have been accessed. Here are all the options for checking access/modify time:

- `-amin n` - the file was last accessed within n minutes ago.
- `-atime n` - the file was last accessed within n days ago.
- `-cmin n` - the file status changed within n minutes ago.
- `-ctime n` - the file status changed within n days ago.
- `-mmin n` - the file was last modified within n minutes ago.
- `-mtime n` - the file was last modified within n days ago.
- `-anewer file` - the searched for file was modified more recently than `[FILE`]. If using `-L` or `-H`, and `[FILE]` is a symbolic link, then the file it points to is used.
- `-cnewer` file - the searched for file status changed more recently than `[FILE]`. If using `-L` or `-H`, and `[FILE]` is a symbolic link, then the file it points to is used.
If you add `-daystart` to the end of any of these, the measurement will be taken from the start of the current day, rather than the current time, i.e. the following will find anything modified within the last 5 days, starting from the beginning of the current day. This option is not available on MacOS.

```
find . -name "*.txt" -mmin 5 -daystart
```

Finally, `+` and `-` modifications are also available. For instance, `-amin -5` will find anything modified in the last 5 minutes, but `-amin +5` will find anything modified more than 5 minutes ago.

## Executing Commands on find command in Linux and MacOS
Once you find some files or directories with the find command, you might want to do something to them. Thankfully, we can use the -exec option to run commands on each of the files or directories found. Any code after -exec will run on every file found.

For example, the below command will change all found files to have an owner called someOwner.

```
find . -name "*.txt" -exec chown someOwner {} \;
```

The `\;` at the end simply signifies the end of the line. The `{}` refers to the current file found - find will substitute in the file name for each file found, so that the command is much more secure.

Note: If you want to do this on a directory, then use `-execdir` instead of `-exec`.

## Delete files with find on Linux and MacOS
It goes without saying that this should be used with caution. find is recursive, and you may unknowingly delete a lot of files you don't intend to. However, if you want to delete files you find with the find command, you can use the -delete flag at the end of your find code. If you put it first, it will delete everything in the folder you specify. So be careful.

The following deletes all files with the form *.txt (i.e. those with a .txt prefix):

```
find . -name "*.txt" -delete
```