# fd User Guide

`fd` is a fast, user-friendly alternative to `find`. You give it a pattern, and it
searches your filesystem for entries whose names match — using a regular expression by
default, or a glob if you ask for one. Out of the box it skips hidden files, honors your
`.gitignore` rules, searches case-insensitively until your pattern says otherwise, and
prints colorized results in parallel across all your CPU cores.

This guide covers everything you can do with `fd` from the command line: installing it,
running your first search, every option it accepts, and recipes for the tasks people reach
for `fd` to solve. Architecture, internals, and deep configuration live in the companion
Admin Guide.

> [!NOTE]
> On Debian, Ubuntu, and their derivatives the binary is installed as **`fdfind`** instead
> of `fd`, because the name `fd` is already taken by another package. Everywhere else in
> this guide, read `fd` as `fdfind` if you installed it that way. Many users add an alias:
> `alias fd=fdfind`.

---

## 1. Quick Start

Find every file or directory whose name contains `netflix`, starting in the current
directory:

```bash
fd netflix
```

```text
projects/netflix-clone
projects/netflix-clone/README.md
notes/netflix-passwords.txt
```

The first argument is a **regular expression**, matched against the *name* of each entry
(not the full path). The search is recursive, skips hidden and ignored files, and is
case-insensitive as long as your pattern is all lowercase.

A few more starters:

```bash
fd '^README'            # names that start with "README"
fd '\.jpg$'             # names ending in .jpg (regex)
fd -e jpg               # the same, but using the extension filter (preferred)
fd -e md -e txt notes   # names containing "notes" with extension md or txt
fd                      # no pattern: list everything (that isn't hidden/ignored)
fd . src                # match everything, but only under the src/ directory
```

> [!TIP]
> When you want *all* files, use `fd` with no pattern, or use `.` as the pattern when you
> also need to give a search directory: `fd . path/to/dir`.

---

## 2. Installation

`fd` is a single self-contained binary written in Rust. There is nothing to configure
after installation and no runtime dependencies (one optional exception: `--list-details`
shells out to `ls`).

=== "Prebuilt binary"

    Every release ships prebuilt binaries for Linux, macOS, and Windows on the project's
    GitHub Releases page. Download the archive for your platform, extract it, and place the
    `fd` executable somewhere on your `PATH`:

    ```bash
    # Example: Linux x86_64
    tar xzf fd-v10.4.2-x86_64-unknown-linux-gnu.tar.gz
    sudo install fd-v10.4.2-x86_64-unknown-linux-gnu/fd /usr/local/bin/
    ```

    Windows release archives are distributed as `.zip` files.

=== "cargo (from crates.io)"

    If you have a Rust toolchain, install the `fd-find` crate. The crate is named
    `fd-find`, but the installed binary is named `fd`:

    ```bash
    cargo install fd-find
    ```

    ```text
    Installing fd-find v10.4.2
    ...
    Installed package `fd-find v10.4.2` (executable `fd`)
    ```

=== "cargo-binstall"

    To grab the prebuilt release binary without compiling, use
    [`cargo-binstall`](https://github.com/cargo-bins/cargo-binstall):

    ```bash
    cargo binstall fd-find
    ```

=== "Build from source"

    ```bash
    git clone https://github.com/sharkdp/fd
    cd fd
    cargo build --release
    # binary is at ./target/release/fd
    ```

> [!IMPORTANT]
> Building from source requires Rust **1.90.0 or newer** (the project's minimum supported
> Rust version) and uses the 2024 edition. Use `rustup update` if your toolchain is older.

> [!NOTE]
> `fd` is also packaged for many operating systems (Homebrew, the major Linux
> distributions, Scoop/Chocolatey on Windows, and more). Package names and the exact
> command vary by system; consult your package manager. Remember the `fdfind` rename on
> Debian/Ubuntu noted above.

### Verifying the installation

```bash
fd --version
```

```text
fd 10.4.2
```

### Shell completions

`fd` can generate completion scripts for your shell on the fly:

```bash
fd --gen-completions bash > fd.bash
fd --gen-completions zsh  > _fd
fd --gen-completions fish > fd.fish
```

If you omit the shell name, `fd` tries to detect it from your environment. Install the
generated file wherever your shell looks for completions.

> [!NOTE]
> Completion generation is only available when `fd` was built with the `completions`
> feature, which is enabled in the default build and in all official release binaries.

---

## 3. How `fd` Searches: The Defaults You Should Know

Before the option reference, it pays to understand the five behaviors `fd` applies unless
you tell it otherwise. They are what make `fd` pleasant — and occasionally surprising.

| Default | What it means | How to turn it off |
|---|---|---|
| **Smart case** | All-lowercase pattern → case-insensitive. Any uppercase letter → case-sensitive. | `-s` (force sensitive) / `-i` (force insensitive) |
| **Skip hidden** | Entries whose name starts with `.` are not shown. | `-H` / `--hidden` |
| **Respect ignore files** | `.gitignore`, `.ignore`, `.fdignore`, and the global ignore are honored. | `-I` / `--no-ignore` |
| **Match the name only** | The pattern is matched against the file *name*, not the whole path. | `-p` / `--full-path` |
| **Regex pattern** | The pattern is a regular expression. | `-g` / `--glob` |

> [!TIP]
> `-u`/`--unrestricted` is the quick "show me everything" switch — it is an alias for
> `--no-ignore --hidden`. Pass it twice (`-uu`) to also disable `.gitignore` handling
> entirely, just like `rg -uu`.

> [!IMPORTANT]
> "Smart case" looks at your pattern for any uppercase character. `fd readme` matches
> `README.md`, but `fd Readme` will not, because the capital `R` switches `fd` into
> case-sensitive mode. This is the single most common source of "why didn't it match?"
> confusion (see issue #2013).

---

## 4. Everyday Usage

This section groups the options by the task you are trying to accomplish. Section 5 is the
exhaustive flag reference if you prefer to look options up directly.

### 4.1 Choosing how the pattern is interpreted

```bash
fd 'foo.*bar'           # regex (default): "foo", any chars, "bar"
fd -g '*.txt'           # glob: shell-style wildcard
fd -F 'a.b.c'           # fixed/literal substring — dots are literal, not regex
fd --exact main.rs      # literal AND whole-name match (not a substring)
```

- **`-g`/`--glob`** switches to glob syntax (`*`, `?`, `[...]`, `**`). A `*` does not
  cross directory separators.
- **`-F`/`--fixed-strings`** (alias `--literal`) treats the pattern as a plain string;
  regex metacharacters lose their meaning. It still matches as a *substring*.
- **`--exact`** is like `--fixed-strings` but the pattern must match the entire name
  (or entire path with `-p`), not just part of it.

Require several patterns at once with `--and` (every pattern must match):

```bash
fd foo --and bar --and '\.txt$'   # name contains foo AND bar AND ends in .txt
```

### 4.2 Controlling case

```bash
fd -s Config        # case-sensitive: matches Config, not config
fd -i CONFIG        # case-insensitive: matches config, Config, CONFIG
```

### 4.3 Including hidden and ignored files

```bash
fd -H secret              # include hidden files (dotfiles, .config, ...)
fd -I target              # include files normally hidden by .gitignore/.ignore
fd -u pattern             # unrestricted: hidden + ignored (= -H -I)
fd -uu pattern            # also ignore .gitignore rules completely
```

Finer-grained ignore control:

| Option | Effect |
|---|---|
| `--no-ignore-vcs` | Stop honoring `.gitignore` (but keep `.ignore`/`.fdignore`). |
| `--no-ignore-parent` | Stop reading ignore files in parent directories. |
| `--no-require-git` | Honor gitignore rules even when not inside a git repository. |
| `--ignore-file <path>` | Add your own ignore file (in `.gitignore` format). |

> [!NOTE]
> By default `fd` only applies `.gitignore` rules when it detects you are inside a git
> repository. If you keep `.gitignore` files outside of git repos and want them respected,
> add `--no-require-git`.

### 4.4 Filtering by type, extension, size, time, and owner

**By type** with `-t`/`--type` (repeatable):

```bash
fd -t f config        # only regular files
fd -t d src           # only directories
fd -t l               # only symlinks
fd -t x               # only executable files
fd -t e               # only empty files or directories
fd -t f -t l config   # files OR symlinks
```

| Value | Aliases | Matches |
|---|---|---|
| `file` | `f` | Regular files |
| `directory` | `d`, `dir` | Directories |
| `symlink` | `l` | Symbolic links |
| `executable` | `x` | Files executable by you (implies `file`) |
| `empty` | `e` | Empty files **or** directories |
| `socket` | `s` | Sockets |
| `pipe` | `p` | Named pipes (FIFOs) |
| `block-device` | `b` | Block devices |
| `char-device` | `c` | Character devices |

**By extension** with `-e`/`--extension` (repeatable). This is cleaner than a regex:

```bash
fd -e md                # all Markdown files
fd -e jpg -e png -e gif # images
fd -e rs main           # Rust files whose name contains "main"
```

**By size** with `-S`/`--size`, using `<+|->NUM<UNIT>`:

```bash
fd -S +10m              # files at least 10 MB
fd -S -1k               # files at most 1 KB
fd -S +1g -S -5g        # between 1 GB and 5 GB (combine constraints)
```

`+` means "at least", `-` means "at most", and no sign means "exactly". Units (case
insensitive): `b` bytes; `k`/`m`/`g`/`t` for decimal KB/MB/GB/TB (powers of 1000);
`ki`/`mi`/`gi`/`ti` for binary KiB/MiB/GiB/TiB (powers of 1024). A trailing `b` is allowed
(`kb`, `mib`).

**By modification time** with `--changed-within` and `--changed-before`:

```bash
fd --changed-within 2weeks            # modified in the last two weeks
fd --changed-within 1d                # modified in the last day
fd --changed-before 2020-01-01        # older than a fixed date
fd --changed-within '2018-10-27 10:00:00'
```

The argument is either a **duration** (`10h`, `1d`, `35min`, `2weeks`) or a **point in
time** (`YYYY-MM-DD`, `YYYY-MM-DD HH:MM:SS`, or `@<unix-timestamp>`). Handy aliases:
`--newer`/`--changed-after`/`--change-newer-than` for `--changed-within`, and
`--older`/`--change-older-than` for `--changed-before`.

**By owner** (Unix only) with `-o`/`--owner`, format `[user|uid][:group|gid]`:

```bash
fd -o john              # owned by user john
fd -o :developers       # owned by group developers
fd -o john:developers   # both
fd -o '!root'           # NOT owned by root (prefix a side with !)
```

### 4.5 Limiting how deep and how wide

```bash
fd -d 2 pattern         # search at most 2 directories deep
fd --min-depth 3        # only show results at least 3 levels down
fd --exact-depth 2      # only results at exactly depth 2
fd -E '*.pyc' -E node_modules pattern   # exclude globs (repeatable)
fd --prune -t d cache   # match dirs named cache but don't descend into them
fd --max-results 5      # stop after 5 results
fd -1 config            # stop at the first result (alias for --max-results=1)
```

> [!TIP]
> `--exclude`/`-E` is faster and more predictable than adding things to an ignore file
> when you just want to skip a directory for one search, e.g. `fd -E .git`.

### 4.6 Choosing where to search

```bash
fd pattern                       # search the current directory
fd pattern ~/projects            # search a specific directory
fd pattern dir1 dir2 dir3        # search several directories
fd --search-path ~/a --search-path ~/b pattern   # same, via an option
fd -C ~/projects pattern         # change working dir first, then search
```

The directory argument(s) come **after** the pattern. `--search-path` is an alternative
that is convenient in scripts. `-C`/`--base-directory` changes `fd`'s working directory
before searching, so results are shown relative to that base.

### 4.7 Shaping the output

```bash
fd -a pattern            # print absolute paths
fd -l pattern            # long "ls -l" listing (size, permissions, dates)
fd -p '**/.git/config'   # match against the full path, not just the name
fd -0 pattern            # separate results with NUL (for xargs -0)
fd -c never pattern      # disable colors (also: NO_COLOR env var)
fd --format '{}.bak'     # apply an output template (see below)
fd --hyperlink           # emit terminal hyperlinks to each result
```

The **format template** (`--format`) and the exec placeholders share the same syntax:

| Placeholder | Expands to |
|---|---|
| `{}` | The full path of the result |
| `{/}` | The basename (filename only) |
| `{//}` | The parent directory |
| `{.}` | The path with its extension removed |
| `{/.}` | The basename with its extension removed |

```bash
fd -e txt --format '{//} -> {/}'
```

```text
notes -> todo.txt
notes -> ideas.txt
```

> [!NOTE]
> `-l`/`--list-details` is essentially `--exec-batch ls -l` with a few `ls` options added.
> On Windows it requires GNU `ls` to be installed (see Troubleshooting).

### 4.8 Running a command on each result

This is `fd`'s most powerful feature. Use `-x`/`--exec` to run a command **per result** (in
parallel), or `-X`/`--exec-batch` to run **one command with all results** as arguments.

```bash
# Run a command for each match (parallel):
fd -e zip -x unzip                 # unzip every .zip file
fd -e jpg -x convert {} {.}.png    # convert each .jpg to .png next to it
fd -e h -e cpp -x clang-format -i  # format each C/C++ file in place

# Run one command with all matches at once (batch):
fd -g 'test_*.py' -X vim           # open all matching files in one editor
fd -e rs -X wc -l                  # count total lines across all .rs files
```

The same `{}`, `{/}`, `{//}`, `{.}`, `{/.}` placeholders apply. If you don't include a
placeholder, `fd` appends an implicit `{}` to the end of your command. Escape literal
braces with `{{` and `}}`.

> [!TIP]
> Put `-x`/`-X` **last** on the command line. Everything after it is treated as part of the
> command, not as `fd` options. If you must continue with more `fd` flags afterward,
> terminate the command template with `\;`.

> [!CAUTION]
> `fd -x` runs commands in **parallel** with no guaranteed order. If your command must run
> one at a time (or order matters), add `-j 1`/`--threads 1`. For `-X` batch mode, if there
> are more results than fit on one command line, `fd` automatically splits them into
> multiple invocations; control the chunk size with `--batch-size`.

### 4.9 Performance and quiet checks

```bash
fd -j 4 pattern         # use 4 threads (default: all available cores)
fd -q pattern           # print nothing; exit 0 if anything matched, else 1
fd --show-errors        # surface permission/dead-symlink errors (normally hidden)
```

`-q`/`--quiet` (alias `--has-results`) is built for scripts:

```bash
if fd -q -e lock; then echo "lock files present"; fi
```

---

## 5. Complete Option Reference

`fd`'s usage is `fd [OPTIONS] [pattern] [path...]`. The table below lists every option.
Options marked *(hidden)* are accepted but not shown in `fd --help`; most have a visible
counterpart they override.

### Search behavior

| Option | Description |
|---|---|
| `-H`, `--hidden` | Include hidden files and directories. |
| `-I`, `--no-ignore` | Don't respect `.gitignore`/`.ignore`/`.fdignore`/global ignore. |
| `--no-ignore-vcs` | Don't respect `.gitignore` files. |
| `--no-require-git` | Respect gitignore rules even outside a git repository. |
| `--no-ignore-parent` | Don't respect ignore files in parent directories. |
| `--no-global-ignore-file` *(hidden)* | Don't respect the global ignore file. |
| `-u`, `--unrestricted` | Alias for `--no-ignore --hidden`; repeat (`-uu`) to also drop `.gitignore`. |
| `-s`, `--case-sensitive` | Case-sensitive search. |
| `-i`, `--ignore-case` | Case-insensitive search. |
| `-g`, `--glob` | Glob-based search instead of regex. |
| `--regex` | Regex-based search (the default; use to override `--glob`). |
| `-F`, `--fixed-strings` (`--literal`) | Treat the pattern as a literal substring. |
| `--exact` | Match the entire filename exactly (literal, non-substring). |
| `--and <pattern>` | Additional required pattern; may be given multiple times. |
| `-p`, `--full-path` | Match the pattern against the full path, not just the name. |

### Filters

| Option | Description |
|---|---|
| `-t`, `--type <filetype>` | Filter by type (`f`, `d`, `l`, `x`, `e`, `s`, `p`, `b`, `c`). Repeatable. |
| `-e`, `--extension <ext>` | Filter by file extension. Repeatable. |
| `-S`, `--size <size>` | Filter by size, e.g. `+10m`, `-1k`, `100ki`. Repeatable. |
| `--changed-within <date\|dur>` | Modified more recently than the given time/duration. |
| `--changed-before <date\|dur>` | Modified before the given time/duration. |
| `-o`, `--owner <user:group>` | (Unix) Filter by owning user/group; `!` negates. |
| `-E`, `--exclude <glob>` | Exclude entries matching a glob. Repeatable. |
| `--ignore-file <path>` | Add a custom ignore file in `.gitignore` format. |
| `--ignore-contain <name>` | Skip directories that contain an entry with this name. |
| `--prune` | Don't descend into matching directories. |

### Depth and result limits

| Option | Description |
|---|---|
| `-d`, `--max-depth <depth>` (`--maxdepth`) | Limit traversal depth. |
| `--min-depth <depth>` (`--mindepth`) | Only show results at or below this depth. |
| `--exact-depth <depth>` | Only show results at exactly this depth. |
| `--max-results <count>` | Stop after this many results. |
| `-1` | Stop at the first result (alias for `--max-results=1`). |
| `-q`, `--quiet` (`--has-results`) | Print nothing; exit 0 on any match, 1 otherwise. |

### Traversal control

| Option | Description |
|---|---|
| `-L`, `--follow` (`--dereference`) | Follow symbolic links. |
| `--one-file-system` (`--mount`, `--xdev`) | Don't cross filesystem boundaries. |
| `-j`, `--threads <num>` | Number of threads for searching/executing. |
| `-C`, `--base-directory <path>` | Change working directory before searching. |
| `[path...]` | Root directories to search (default: current directory). |
| `--search-path <path>` | Search root as an option instead of a positional argument. Repeatable. |

### Output

| Option | Description |
|---|---|
| `-a`, `--absolute-path` | Print absolute instead of relative paths. |
| `-l`, `--list-details` | Long listing format (like `ls -l`). |
| `-0`, `--print0` | Separate results with the NUL character. |
| `--format <fmt>` | Print results using a template (`{}`, `{/}`, `{//}`, `{.}`, `{/.}`). |
| `-c`, `--color <when>` | Colorize: `auto` (default), `always`, `never`. |
| `--hyperlink[=<when>]` | Emit terminal hyperlinks: `auto`, `always`, `never` (default). |
| `--path-separator <sep>` | Override the path separator in printed paths. |
| `--strip-cwd-prefix[=<when>]` | Control stripping of the leading `./`: `auto`, `always`, `never`. |

### Command execution

| Option | Description |
|---|---|
| `-x`, `--exec <cmd>...` | Run a command for each result, in parallel. |
| `-X`, `--exec-batch <cmd>...` | Run one command with all results as arguments. |
| `--batch-size <size>` | Max arguments per `-X` invocation (0 = unlimited). |

### Other

| Option | Description |
|---|---|
| `--show-errors` | Show filesystem errors (permissions, dead symlinks). |
| `--gen-completions [shell]` *(hidden)* | Generate a shell completion script. |
| `-h`, `--help` | Print help (`--help` shows the long help). |
| `-V`, `--version` | Print version information. |

> [!NOTE]
> Several "negative" flags exist purely to override an earlier flag on the command line —
> `--no-hidden`, `--ignore`, `--ignore-vcs`, `--require-git`, `--ignore-parent`,
> `--relative-path`, `--no-follow`. They are hidden from help because you rarely type them
> directly; `fd` uses "last one wins" semantics so a later flag overrides an earlier one.

---

## 6. Recipes

Practical one-liners for common jobs.

**Find and delete all `.DS_Store` files:**

```bash
fd -H -t f '\.DS_Store$' -X rm
```

**Find large log files and compress them:**

```bash
fd -e log -S +100m -x gzip
```

**Rename `.jpeg` files to `.jpg`:**

```bash
fd -e jpeg -x mv {} {.}.jpg
```

**List the 10 most recently modified source files:**

```bash
fd -e rs --changed-within 7d
```

**Pipe results into another tool safely (handles spaces/newlines in names):**

```bash
fd -0 -e txt | xargs -0 wc -l
```

**Search only the top level (no recursion):**

```bash
fd -d 1
```

**Find empty directories and remove them:**

```bash
fd -t e -t d -X rmdir
```

**Count files by running a batch command:**

```bash
fd -t f -X echo | wc -w
```

**Open all matching files in your editor at once:**

```bash
fd -g '*.conf' /etc -X $EDITOR
```

> [!WARNING]
> Recipes that delete or overwrite (`rm`, `mv`, `gzip`) act on whatever `fd` matches. Run
> the search **without** `-x`/`-X` first to review the list, then add the command.

---

## 7. Ignoring Files Permanently

Beyond `.gitignore`, `fd` reads two ignore files of its own:

- **`.fdignore`** — placed anywhere in your project, same syntax as `.gitignore`. Applies
  to `fd` only.
- **Global ignore file** — patterns that apply to every `fd` search on your machine.

The global ignore file lives in `fd`'s config directory: on Linux/macOS that is
`~/.config/fd/ignore` (or `$XDG_CONFIG_HOME/fd/ignore`). Create it and add one glob per
line:

```text
# ~/.config/fd/ignore
.git/
node_modules/
*.tmp
```

> [!TIP]
> Use `.fdignore` for project-specific noise you don't want to add to `.gitignore`, and the
> global ignore file for things you never want to see anywhere (build caches, editor temp
> files).

---

## 8. Exit Codes

`fd` returns a standard exit code so you can use it in scripts and pipelines.

| Code | Meaning |
|---|---|
| `0` | Success. (With `-q`/`--quiet`: at least one match was found.) |
| `1` | A general error occurred. (With `-q`/`--quiet`: no match was found.) |
| `130` | Interrupted by <kbd>Ctrl</kbd>+<kbd>C</kbd> (SIGINT). |

> [!NOTE]
> When you use `-x`/`-X`, `fd`'s exit code reflects the commands it ran: if any executed
> command exits non-zero, `fd` exits `1`.

---

## 9. Troubleshooting

Each entry shows the exact message `fd` prints (all errors are prefixed with
`[fd error]:`), why it happens, and how to fix it.

### Error: `The search pattern '...' contains a path-separation character and will not lead to any search results.`

**Cause:** Your pattern contains a `/` (or, on Windows, a `\` that names a real directory).
By default `fd` matches only the file *name*, so a pattern with a path separator can never
match.

**Solution:** To list everything inside a directory, use a match-all pattern and pass the
directory as the search path: `fd . some/dir`. To match against the full path instead, add
`-p`/`--full-path`: `fd -p some/dir`.

**Prevention:** Remember that the default search target is the name only; reach for `-p`
when you mean the whole path.

### Error: `The pattern(s) seems to only match files with a leading dot, but hidden files are filtered by default...`

**Cause:** Your pattern (e.g. `^\.gitignore`) only matches hidden files, but hidden files
are skipped by default, so the search would always return nothing.

**Solution:** Add `-H`/`--hidden` to include hidden files, or adjust the pattern.

### Why does `fd` search case-insensitively / case-sensitively unexpectedly?

**Cause:** Smart case. An all-lowercase pattern is case-insensitive; any uppercase
character makes the whole search case-sensitive (issue #2013).

**Solution:** Force the behavior explicitly with `-i` (insensitive) or `-s` (sensitive).

### Error: `'...' is not a valid size constraint. See 'fd --help'.`

**Cause:** A malformed `-S`/`--size` value. The format is `<+|->NUM<UNIT>`, e.g. `+10m`.

**Solution:** Use a sign (`+`/`-`/none), a number, and a valid unit (`b`, `k`, `m`, `g`,
`t`, `ki`, `mi`, `gi`, `ti`). Examples: `-S +1g`, `-S -500k`, `-S 1mi`.

### Error: `'...' is not a valid date or duration. See 'fd --help'.`

**Cause:** A `--changed-within`/`--changed-before` value that isn't a recognized duration
or timestamp.

**Solution:** Use a duration like `2weeks`, `1d`, `35min`, or a date like `2020-01-01`,
`'2020-01-01 12:00:00'`, or `@1577836800` (Unix timestamp with a leading `@`).

### Error: `'...' is not a recognized user name` / `'...' is not a recognized group name`

**Cause:** The `-o`/`--owner` value names a user or group that doesn't exist on the system.

**Solution:** Use a valid name, or a numeric uid/gid. Format: `user:group`, either side
optional, `!` to negate.

### Error: `'fd --list-details' is not supported on Windows unless GNU 'ls' is installed.`

**Cause:** `-l`/`--list-details` shells out to `ls`, which isn't present on a stock Windows
system (issue #1482, common with nushell).

**Solution:** Install GNU `ls` (e.g. via Git for Windows / MSYS2 / coreutils) and ensure
it's on your `PATH`, or avoid `-l` on Windows and use `--format` instead.

### Error: `A path separator must be exactly one byte, but the given separator is N bytes: '...'.`

**Cause:** On Windows, some shells expand `/` in arguments, so `--path-separator /` arrives
as something longer.

**Solution:** Use `//` instead, as the message suggests.

### Error: `Command not found: ...` (e.g. with `-x cd`)

**Cause:** `-x`/`-X` execute real programs, not shell built-ins. `cd`, `export`, and
similar are shell built-ins, not executables (issue #1944).

**Solution:** Wrap the built-in in a shell: `fd -x bash -c 'cd {} && ...'`.

### Error: `No executable provided for --exec or --exec-batch`

**Cause:** `-x`/`-X` was given without a command to run.

**Solution:** Provide the command, e.g. `fd -e txt -x cat`.

### Error: `Only one placeholder allowed for batch commands` / `First argument of exec-batch is expected to be a fixed executable`

**Cause:** With `-X`/`--exec-batch`, the command may contain at most one placeholder, and
the program name (first argument) must be fixed, not a placeholder.

**Solution:** Restructure the batch command so the executable is literal and only one
placeholder appears, e.g. `fd -e rs -X wc -l`.

### Error: `Search path '...' is not a directory.` / `No valid search paths given.`

**Cause:** A path argument doesn't point to an existing directory.

**Solution:** Check the path. `fd` warns about each bad path and exits with "No valid
search paths given" if none remain.

### `fd` doesn't seem to exit when its output pipe is closed

**Cause:** A known edge case with full-path search and globbing when the downstream of a
pipe closes (issue #1479).

**Solution:** Track the upstream issue; for most pipelines `fd` exits cleanly on a broken
pipe.

---

## 10. Frequently Asked Questions

**Q: Is `fd` a drop-in replacement for `find`?**
A: No — it's an alternative with friendlier defaults and syntax, not a `find` clone. It
covers the most common `find` use cases with far less typing, but doesn't replicate every
`find` expression.

**Q: How do I search for *all* files, including hidden and ignored ones?**
A: `fd -u` (or `fd -uu` to also ignore `.gitignore` rules). `-u` is short for
`--no-ignore --hidden`.

**Q: Why didn't my uppercase pattern match a lowercase file?**
A: Smart case made the search case-sensitive because the pattern has an uppercase letter.
Use `-i` to force case-insensitive matching.

**Q: How do I match against the whole path instead of just the filename?**
A: Use `-p`/`--full-path`, e.g. `fd -p '**/.git/config'`.

**Q: What's the difference between `--glob` and the default?**
A: The default is a regular expression. `--glob` switches to shell-style wildcards
(`*`, `?`, `[...]`).

**Q: How do I exclude a directory like `node_modules`?**
A: `fd -E node_modules`, or add it to a `.fdignore`/global ignore file.

**Q: How do I run a command on every result?**
A: `fd <pattern> -x <command>` (per result, parallel) or `-X` (all results at once).
Place `-x`/`-X` last.

**Q: How do I make `-x` run commands one at a time?**
A: Add `-j 1` to use a single thread.

**Q: How do I get NUL-separated output for `xargs`?**
A: `fd -0 ... | xargs -0 ...`.

**Q: Why are colors disabled when I pipe `fd` into another command?**
A: Color defaults to `auto`, which only colorizes an interactive terminal. Force it with
`-c always`. You can also disable color globally with the `NO_COLOR` environment variable.

**Q: How do I limit search depth?**
A: `-d N`/`--max-depth N`. Combine with `--min-depth`/`--exact-depth` for a depth window.

**Q: How do I filter by size or modification time?**
A: `-S +10m` (size) and `--changed-within 2weeks` / `--changed-before 2020-01-01` (time).

**Q: Does `fd` follow symlinks?**
A: Not by default. Add `-L`/`--follow`.

**Q: Where do I report bugs?**
A: On GitHub at <https://github.com/sharkdp/fd/issues>.

**Q: The binary is called `fdfind` on my system — why?**
A: On Debian/Ubuntu the name `fd` was already taken, so the package installs the binary as
`fdfind`. Add `alias fd=fdfind` to your shell config.

---

_Generated June 2026 from sharkdp/fd at f7d4d71. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
