1. Overview

While working with Linux, we often want to search for files from the terminal.

The built-in find command is widely used for this purpose. However, there is an alternative command – fd – which has some additional features, including friendlier colorized output, faster search speed, and some useful defaults.

In this tutorial, we’ll look at how to use fd.

2. Installation

The fd utility is available in almost all package repositories. We can install the fd package in OpenSUSE, Fedora, or Manjaro. In Ubuntu 19.04 and newer, we can install the fd-find package:

$ sudo apt install fd-find

Although the command name is fdfind in Ubuntu, we can set an alias:

$ alias fd=fdfind

3. Creating Test Files

For our examples, let’s quickly create some files in a temporary directory:

$ mkdir -p /tmp/baeldung-fd/one /tmp/baeldung-fd/two
$ cd /tmp/baeldung-fd/
$ touch one/test-File.txt two/test-File.txt
$ echo '#!/bin/sh\n:' | tee one/.hiddenFile.sh one/test-File.sh two/.hiddenFile.sh two/test-File.sh
$ chmod +x one/test-File.sh

After this step, we have a few normal text files, hidden files, and shell scripts. We’ve used the tee command to save the output of the echo command to all four files.

We’ve also set our current working directory to /tmp/baeldung-fd.

Let’s view the directory structure with the tree command:

$ tree -a
├── one
│   ├── .hiddenFile.sh
│   ├── test-File.sh
│   └── test-File.txt
└── two
    ├── .hiddenFile.sh
    ├── test-File.sh
    └── test-File.txt

2 directories, 6 files

4. Basic Usage

With no additional parameters, we can run fd to view the contents of the current directory:

$ fd

As we can see, fd does not show hidden files by default. This output will also be colorized if our terminal supports it.

The power of fd comes from the filters we apply. When we add filters, we can also provide a path argument to tell fd to search in that path, rather than the current directory.

Let’s look at how to filter.

4.1. Regular Expressions

By default, fd treats the search pattern as a regular expression and performs a case-insensitive search:

$ fd 'file[.]sh'

Here our file[.]sh expression was looking for any file containing file.sh insensitive of case.

As the dot character is a regular expression wildcard, we enclosed it in square brackets [] to quote it. However, we can use the dot character unquoted to match any file in a particular directory:

$ fd . two

As we can only specify the path if we specify a pattern, the dot (.) is a useful match-all pattern.

4.2. Wildcard Match

If we wish to use wildcards like the asterisk (*), as we might in other shell commands, instead of regular expressions, then the -g flag enables file globbing or matching by wildcard:

$ fd 'test-*.sh' -g

4.3. Simple String Match

Sometimes we need to match a string containing regular expression special characters. Though we can quote them, it is easier to indicate that the parameter should be matched as it is by using the -F flag:

$ fd -F 'file.sh'

This simple string match works by matching the pattern as a substring.

We can enable case-sensitivity with the -s flag.

So, while the default search for file finds results:

$ fd file ./one

With the flag turned on, it no longer matches:

$ fd -s file ./one
# no match

Also, the case sensitive mode is automatically enabled if the pattern contains an uppercase character:

$ fd filE ./one
# no match

4.5. Show Hidden Files

fd omits hidden files by default. We can include the hidden files in the search result with the -H flag:

$ fd -H file ./two

5. Specifying Search Criteria

5.1. Search by File Type

We can search for a file type with the -t flag and a file type indicator. Some common file type indicators:

  • f, file – regular files
  • d, directory – directories
  • l, symlink – symbolic links
  • x, executable – executable files
  • e, empty – empty files or directories

Let’s try to list all subdirectories. Here we can use either directory or d after the -t flag:

$ fd -t directory

We can repeat the -t flag to combine several file type criteria. To find all empty files, we can use the -t flag twice.

$ fd -t e -t f

In this example, the first -t flag with argument e matches empty files or directories. The second -t flag with argument f matches regular files. The combination gives us the list of regular files that are empty.

5.2. Search by File Extension

We can also use the -e flag to search for files having a particular extension. To find files ending with extension sh:

$ fd -e sh

We can repeat the -e flag to match multiple extensions as well. For example, to search for the files with extensions sh or txt:

$ fd -e sh -e txt

5.3. Matching the Full Path

By default, the search pattern is only matched against the name of the file or directory. With the -p flag, the pattern is matched against the full path:

Let’s search for all files in the /tmp directory whose full path matches a given regular expression:

$ fd -p 'baeldung.*sh' /tmp 

As we can see, the regular expression matches the absolute path of the files. We should note that this is still a substring match, though we may add regular expression anchors ^ and $ to force the match to include the start or end of the path, respectively.

5.4. Search in Multiple Locations

By default, fd searches in the current directory. To perform the search in some specific directories, we can specify multiple path arguments after the pattern.

We can search for all files in directories one and two:

$ fd . ./one ./two -t f 

There are three components in this example:

  1. We use a single dot as the required file pattern to match anything.
  2. ./one and ./two are the paths where we are searching.
  3. -t f matches regular files and omits directories from the result.

6. Advanced Usage

By default, fd does not follow symbolic links. We can traverse symbolic links using the -L flag.

First, let’s create a symbolic link of the subdirectory named one with the ln command:

$ ln -s one symone

Now let’s search for an executable file:

$ fd -t x

As we can see, it does not show the contents of the newly created symbolic link. Let’s include the contents of the symlink by using the -L flag:

$ fd -t x -L

Now we have the contents of the symbolic link as well.

Sometimes we want to avoid traversing another filesystem while following symbolic links. We can prevent entering another filesystem by using the –one-file-system flag. 

6.2. Control Directory Traversal Depth

We can also control the directory traversal depth using the flags -d, –min-depth, and –exact-depth. Let’s create a few directories, one within another:

$ mkdir -p ./two/sub/moresub

This command searches for all files and directories, however, maximum depth is limited to 2:

$ fd -d 2

Conversely, we can specify to find files at least 2 levels below the current directory:

$ fd --min-depth 2 

And, we can perform our searches at a certain depth:

$ fd --exact-depth 2 

6.3. Invert Search Result

Sometimes we want to invert the search result so that only the files or directories that do not match a given pattern are listed. The -E flag shows results that do not match the given glob pattern. We should note that this flag does not support regular expressions.

For example, the wildcard pattern *.sh matches files with extension sh. If we want to search for any file that does not end with extension sh, we can use the following command:

$ fd -E '*.sh' -t f

Here, fd has returned all files and excluded the files matching wildcard *.sh from the result.

6.4. Filter by Size

The -S or –size flag allows us to specify the file size limit. To understand with an example, let’s create a 2 KB file with the dd command in directory two:

$ dd if=/dev/random of=./two/largefile count=4 2> /dev/null

To search for files with size 1 KB or larger, we can use the expression +1k with the -S flag:

$ fd -S +1k 

The result is the file we just created with the dd command, as its size meets our criteria.

Conversely, we can use -1k to search for 1 KB or smaller files:

$ fd -S -1k

Similarly, we can use b for bytes, and m for megabytes, for example. The comprehensive list is available on the man page.

6.5. Filter by Date

Sometimes we need to search for files on the basis of creation date, modified date, or the last access date. We can filter by modified date using the –changed-within and –changed-before flags. These two flags accept both timestamp and duration as an argument.

We can specify the duration in units such as week, day, or min. We can also use the plural forms of the duration units:

$ fd -t x --changed-before "2020-09-01 11:00:00"
$ fd -t x --changed-within 2day
$ fd -t x --changed-within 2days

However, fd does not support searching by created date or last access date.

7. Execute Commands on Search Results

Sometimes, we want to process the result of a file search. We can pass the result to xargs to run some commands on the result set. However, fd allows us to invoke commands directly. The following expressions are expanded before the execution of the command:

  • {} path
  • {.} path without file extension
  • {/} basename
  • {/.} basename without file extension
  • {//} parent directory

7.1. Batch Execution

We can run a command only once on the whole result set with the -X flag. In this mode, fd passes the search result as a list of arguments to the given command.

Let’s pass our results to the file command, which outputs the type of the files on its command line:

$ fd -t f -X file
one/test-File.sh:  POSIX shell script, ASCII text executable 
one/test-File.txt: empty 
two/largefile:     data 
two/test-File.sh:  POSIX shell script, ASCII text executable 
two/test-File.txt: empty

As we can see, the above command is equivalent to the following command where all the arguments are passed at once:

$ file one/test-File.sh one/test-File.txt two/largefile two/test-File.sh two/test-File.txt

7.2. Repeated Execution

On the other hand, we can run a command on each entry of the result set with the -x flag. To understand how we can run a particular command on each entry of the result set, let’s use the -x flag to create a backup copy of each file.

For example, let’s tell fd to invoke the cp command in the specified format on each entry of the search result:

$ fd -Ht f -x cp {} {}.bak

Now let’s check that new files with the extension .bak were created:

$ fd -Ht f -e bak

As we can see, we have created backups by executing cp with the -x flag.

8. Comparison with find

According to the benchmark on its GitHub page, fd runs much faster than the find command. As opposed to find, fd colorizes the output, ignores hidden files, and treats the input search pattern as a regular expression by default.

On the other hand, fd does not support all the functionalities of the find command. Some options such as the -prune flag of the find command are not available with fd. The find command also provides more control over the formatting of the output.

9. Conclusion

In this tutorial, we explored several ways to search for files using fd. We also saw how to further limit the searches using a number of filter criteria. Finally, we briefly compared fd with the find command.

Comments are closed on this article!