Repository: junegunn/fzf
Pull request #3624 (2024-02-12 13:09:53)

Bump crate-ci/typos from 1.17.2 to 1.18.2
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.17.2 to 1.18.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/crate-ci/typos/releases">crate-ci/typos's releases</a>.</em></p>
<blockquote>
<h2>v1.18.2</h2>
<h2>[1.18.2] - 2024-02-08</h2>
<h3>Features</h3>
<ul>
<li>Add <code>--sort</code> flag</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Protect against crash on multi-byte UTF-8 characters when parsed as ASCII</li>
</ul>
<h2>v1.18.1</h2>
<h2>[1.18.1] - 2024-02-05</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct derivate to derivative</li>
</ul>
<h2>v1.18.0</h2>
<h2>[1.18.0] - 2024-02-01</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a href="https://redirect.github.com/crate-ci/typos/issues/897">January 2024</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's changelog</a>.</em></p>
<blockquote>
<h2>[1.18.2] - 2024-02-08</h2>
<h3>Features</h3>
<ul>
<li>Add <code>--sort</code> flag</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Protect against crash on multi-byte UTF-8 characters when parsed as ASCII</li>
</ul>
<h2>[1.18.1] - 2024-02-05</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct derivate to derivative</li>
</ul>
<h2>[1.18.0] - 2024-02-01</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a href="https://redirect.github.com/crate-ci/typos/issues/897">January 2024</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/crate-ci/typos/commit/b63f421581dce830bda2f597a678cb7776b41877"><code>b63f421</code></a> chore: Release</li>
<li><a href="https://github.com/crate-ci/typos/commit/b4e5cd9a1735531e2fe6a385b838cf0f152f5c93"><code>b4e5cd9</code></a> docs: Update changelog</li>
<li><a href="https://github.com/crate-ci/typos/commit/bf9ee1f3b1df9a4b9cff0c67c56888a0b025269c"><code>bf9ee1f</code></a> Merge pull request <a href="https://redirect.github.com/crate-ci/typos/issues/930">#930</a> from epage/fix</li>
<li><a href="https://github.com/crate-ci/typos/commit/8879269b0d6c74ac3aec50c2beed5eb4bb16669a"><code>8879269</code></a> fix(token): Don't crash on parsing unicode</li>
<li><a href="https://github.com/crate-ci/typos/commit/4c248c85ecaf98c43edc2664b71a759c07c5a1ab"><code>4c248c8</code></a> Merge pull request <a href="https://redirect.github.com/crate-ci/typos/issues/929">#929</a> from epage/sort</li>
<li><a href="https://github.com/crate-ci/typos/commit/eb99975267fd41dfc3118a870dd4944ff7c58ac7"><code>eb99975</code></a> feat(cli): Add a --sort flag</li>
<li><a href="https://github.com/crate-ci/typos/commit/ad80305210d4d6dd2444d66b439b75acf2096e0b"><code>ad80305</code></a> fix(cli): Actually run single-threaded</li>
<li><a href="https://github.com/crate-ci/typos/commit/53a7a511710f8a2a68a2d99fa5bbfc2b8d86db92"><code>53a7a51</code></a> chore(ci): See if setting columns helps</li>
<li><a href="https://github.com/crate-ci/typos/commit/ba0d73e4805e5ee9cc0906d9648220c0b4c35927"><code>ba0d73e</code></a> Merge pull request <a href="https://redirect.github.com/crate-ci/typos/issues/928">#928</a> from epage/divan</li>
<li><a href="https://github.com/crate-ci/typos/commit/7cc583fdf168b6ed9df795af0642981d811c617d"><code>7cc583f</code></a> test(bench): Switch to Divan</li>
<li>Additional commits viewable in <a href="https://github.com/crate-ci/typos/compare/v1.17.2...v1.18.2">compare view</a></li>
</ul>
</details>
<br />

<details>
<summary>Most Recent Ignore Conditions Applied to This Pull Request</summary>

| Dependency Name | Ignore Conditions |
| --- | --- |
| crate-ci/typos | [< 1.17, > 1.16.4] |
</details>


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.17.2&new-version=1.18.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml
index 7eee27b4..49dc26a1 100644
--- a/.github/workflows/typos.yml
+++ b/.github/workflows/typos.yml
@@ -7,4 +7,4 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v3
-    - uses: crate-ci/typos@v1.17.2
+    - uses: crate-ci/typos@v1.18.2
diff --git a/BUILD.md b/BUILD.md
index af0a04e9..18630e14 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -42,6 +42,8 @@ Third-party libraries used
     - Licensed under [MIT](http://mattn.mit-license.org)
 - [tcell](https://github.com/gdamore/tcell)
     - Licensed under [Apache License 2.0](https://github.com/gdamore/tcell/blob/master/LICENSE)
+- [fastwalk](https://github.com/charlievieth/fastwalk)
+    - Licensed under [MIT](https://raw.githubusercontent.com/charlievieth/fastwalk/master/LICENSE)
 
 License
 -------
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf619c58..f2d9354c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,28 @@
 CHANGELOG
 =========
 
+0.47.0
+------
+- Replaced ["the default find command"][find] with a built-in directory traversal to simplify the code and to achieve better performance and consistent behavior across platforms.
+  This doesn't affect you if you have `$FZF_DEFAULT_COMMAND` set.
+    - Breaking changes:
+        - Unlike [the previous "find" command][find], the new traversal code will list hidden files, but hidden directories will still be ignored
+        - No filtering of `devtmpfs` or `proc` types
+        - Traversal is parallelized, so the order of the entries will be different each time
+    - You would wonder why fzf implements directory traversal anyway when it's a filter program following the Unix philosophy.
+      But fzf has had [the traversal code for years][walker] to tackle the performance problem on Windows. And I decided to use the same approach on different platforms as well for the benefits listed above.
+    - Built-in traversal is now done using the excellent [charlievieth/fastwalk][fastwalk] library, which easily outperforms its competitors and supports safely following symlinks.
+- Added `$FZF_DEFAULT_OPTS_FILE` to allow managing default options in a file
+    - See [#3618](https://github.com/junegunn/fzf/pull/3618)
+    - Option precedence from lower to higher
+        1. Options read from `$FZF_DEFAULT_OPTS_FILE`
+        1. Options from `$FZF_DEFAULT_OPTS`
+        1. Options from command-line arguments
+
+[find]: https://github.com/junegunn/fzf/blob/0.46.1/src/constants.go#L60-L64
+[walker]: https://github.com/junegunn/fzf/pull/1847
+[fastwalk]: https://github.com/charlievieth/fastwalk
+
 0.46.1
 ------
 - Bug fixes and improvements
diff --git a/README-VIM.md b/README-VIM.md
index e02a97f6..6751d25a 100644
--- a/README-VIM.md
+++ b/README-VIM.md
@@ -238,19 +238,20 @@ call fzf#run({'sink': 'e'})
 ```
 
 We haven't specified the `source`, so this is equivalent to starting fzf on
-command line without standard input pipe; fzf will use find command (or
-`$FZF_DEFAULT_COMMAND` if defined) to list the files under the current
-directory. When you select one, it will open it with the sink, `:e` command.
-If you want to open it in a new tab, you can pass `:tabedit` command instead
-as the sink.
+command line without standard input pipe; fzf will traverse the file system
+under the current directory to get the list of files. (If
+`$FZF_DEFAULT_COMMAND` is set, fzf will use the output of the command
+instead.) When you select one, it will open it with the sink, `:e` command. If
+you want to open it in a new tab, you can pass `:tabedit` command instead as
+the sink.
 
 ```vim
 call fzf#run({'sink': 'tabedit'})
 ```
 
-Instead of using the default find command, you can use any shell command as
-the source. The following example will list the files managed by git. It's
-equivalent to running `git ls-files | fzf` on shell.
+You can use any shell command as the source to generate the list. The
+following example will list the files managed by git. It's equivalent to
+running `git ls-files | fzf` on shell.
 
 ```vim
 call fzf#run({'source': 'git ls-files', 'sink': 'e'})
diff --git a/README.md b/README.md
index 285ba4fc..e0b367b6 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,21 @@
+<div align="center">
+<sup>Special thanks to:</sup>
+<br>
+<br>
+<a href="https://warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=fzf_20240209">
+  <div>
+    <img src="https://raw.githubusercontent.com/junegunn/i/master/warp.png" width="300" alt="Warp">
+  </div>
+  <b>Warp is a modern, Rust-based terminal with AI built in so you and your team can build great software, faster.</b>
+  <div>
+    <sup>Visit warp.dev to learn more.</sup>
+  </div>
+</a>
+<br>
+<hr>
+</div>
+<br>
+
 <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf.png" height="170" alt="fzf - a command-line fuzzy finder"> [![github-actions](https://github.com/junegunn/fzf/workflows/Test%20fzf%20on%20Linux/badge.svg)](https://github.com/junegunn/fzf/actions)
 ===
 
@@ -26,7 +44,7 @@ I would like to thank all the sponsors of this project who make it possible for
 
 If you'd like to sponsor this project, please visit https://github.com/sponsors/junegunn.
 
-<!-- sponsors --><a href="https://github.com/miyanokomiya"><img src="https://github.com/miyanokomiya.png" width="60px" alt="miyanokomiya" /></a><a href="https://github.com/jonhoo"><img src="https://github.com/jonhoo.png" width="60px" alt="Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757"><img src="https://github.com/AceofSpades5757.png" width="60px" alt="Kyle L. Davis" /></a><a href="https://github.com/Frederick888"><img src="https://github.com/Frederick888.png" width="60px" alt="Frederick Zhang" /></a><a href="https://github.com/moritzdietz"><img src="https://github.com/moritzdietz.png" width="60px" alt="Moritz Dietz" /></a><a href="https://github.com/mikker"><img src="https://github.com/mikker.png" width="60px" alt="Mikkel Malmberg" /></a><a href="https://github.com/pldubouilh"><img src="https://github.com/pldubouilh.png" width="60px" alt="Pierre Dubouilh" /></a><a href="https://github.com/rcorre"><img src="https://github.com/rcorre.png" width="60px" alt="Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev"><img src="https://github.com/blissdev.png" width="60px" alt="Jordan Arentsen" /></a><a href="https://github.com/mislav"><img src="https://github.com/mislav.png" width="60px" alt="Mislav Marohnić" /></a><a href="https://github.com/aexvir"><img src="https://github.com/aexvir.png" width="60px" alt="Alex Viscreanu" /></a><a href="https://github.com/dbalatero"><img src="https://github.com/dbalatero.png" width="60px" alt="David Balatero" /></a><a href="https://github.com/comatory"><img src="https://github.com/comatory.png" width="60px" alt="Ondrej Synacek" /></a><a href="https://github.com/moobar"><img src="https://github.com/moobar.png" width="60px" alt="" /></a><a href="https://github.com/majjoha"><img src="https://github.com/majjoha.png" width="60px" alt="Mathias Jean Johansen" /></a><a href="https://github.com/benelan"><img src="https://github.com/benelan.png" width="60px" alt="Ben Elan" /></a><a href="https://github.com/pawelduda"><img src="https://github.com/pawelduda.png" width="60px" alt="Paweł Duda" /></a><a href="https://github.com/slezica"><img src="https://github.com/slezica.png" width="60px" alt="Santiago Lezica" /></a><a href="https://github.com/pbwn"><img src="https://github.com/pbwn.png" width="60px" alt="" /></a><a href="https://github.com/timgluz"><img src="https://github.com/timgluz.png" width="60px" alt="Timo Sulg" /></a><a href="https://github.com/pyrho"><img src="https://github.com/pyrho.png" width="60px" alt="Damien Rajon" /></a><a href="https://github.com/ArtBIT"><img src="https://github.com/ArtBIT.png" width="60px" alt="ArtBIT" /></a><a href="https://github.com/da-moon"><img src="https://github.com/da-moon.png" width="60px" alt="" /></a><a href="https://github.com/hovissimo"><img src="https://github.com/hovissimo.png" width="60px" alt="Hovis" /></a><a href="https://github.com/dariusjonda"><img src="https://github.com/dariusjonda.png" width="60px" alt="Darius Jonda" /></a><a href="https://github.com/mortymacs"><img src="https://github.com/mortymacs.png" width="60px" alt="Morteza NourelahiAlamdari" /></a><a href="https://github.com/cristiand391"><img src="https://github.com/cristiand391.png" width="60px" alt="Cristian Dominguez" /></a><a href="https://github.com/eliangcs"><img src="https://github.com/eliangcs.png" width="60px" alt="Chang-Hung Liang" /></a><a href="https://github.com/asphaltbuffet"><img src="https://github.com/asphaltbuffet.png" width="60px" alt="Ben Lechlitner" /></a><a href="https://github.com/yash1th"><img src="https://github.com/yash1th.png" width="60px" alt="yash" /></a><a href="https://github.com/looshch"><img src="https://github.com/looshch.png" width="60px" alt="george looshch" /></a><a href="https://github.com/kg8m"><img src="https://github.com/kg8m.png" width="60px" alt="Takumi KAGIYAMA" /></a><a href="https://github.com/polm"><img src="https://github.com/polm.png" width="60px" alt="Paul O'Leary McCann" /></a><a href="https://github.com/rbeeger"><img src="https://github.com/rbeeger.png" width="60px" alt="Robert Beeger" /></a><a href="https://github.com/veebch"><img src="https://github.com/veebch.png" width="60px" alt="VEEB Projects" /></a><a href="https://github.com/khuedoan"><img src="https://github.com/khuedoan.png" width="60px" alt="Khue Doan" /></a><a href="https://github.com/yowayb"><img src="https://github.com/yowayb.png" width="60px" alt="Yoway Buorn" /></a><a href="https://github.com/scalisi"><img src="https://github.com/scalisi.png" width="60px" alt="Josh Scalisi" /></a><a href="https://github.com/alecbcs"><img src="https://github.com/alecbcs.png" width="60px" alt="Alec Scott" /></a><a href="https://github.com/thnxdev"><img src="https://github.com/thnxdev.png" width="60px" alt="thanks.dev" /></a><a href="https://github.com/artursapek"><img src="https://github.com/artursapek.png" width="60px" alt="Artur Sapek" /></a><a href="https://github.com/ramnes"><img src="https://github.com/ramnes.png" width="60px" alt="Guillaume Gelin" /></a><a href="https://github.com/mikkifr"><img src="https://github.com/mikkifr.png" width="60px" alt="Mikki Freeman" /></a><a href="https://github.com/jyc"><img src="https://github.com/jyc.png" width="60px" alt="" /></a><a href="https://github.com/Bombycinous"><img src="https://github.com/Bombycinous.png" width="60px" alt="" /></a><a href="https://github.com/mrcnski"><img src="https://github.com/mrcnski.png" width="60px" alt="Marcin S." /></a><a href="https://github.com/roblevy"><img src="https://github.com/roblevy.png" width="60px" alt="Rob Levy" /></a><!-- sponsors -->
+<!-- sponsors --><a href="https://github.com/miyanokomiya"><img src="https://github.com/miyanokomiya.png" width="60px" alt="miyanokomiya" /></a><a href="https://github.com/jonhoo"><img src="https://github.com/jonhoo.png" width="60px" alt="Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757"><img src="https://github.com/AceofSpades5757.png" width="60px" alt="Kyle L. Davis" /></a><a href="https://github.com/Frederick888"><img src="https://github.com/Frederick888.png" width="60px" alt="Frederick Zhang" /></a><a href="https://github.com/moritzdietz"><img src="https://github.com/moritzdietz.png" width="60px" alt="Moritz Dietz" /></a><a href="https://github.com/mikker"><img src="https://github.com/mikker.png" width="60px" alt="Mikkel Malmberg" /></a><a href="https://github.com/pldubouilh"><img src="https://github.com/pldubouilh.png" width="60px" alt="Pierre Dubouilh" /></a><a href="https://github.com/rcorre"><img src="https://github.com/rcorre.png" width="60px" alt="Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev"><img src="https://github.com/blissdev.png" width="60px" alt="Jordan Arentsen" /></a><a href="https://github.com/mislav"><img src="https://github.com/mislav.png" width="60px" alt="Mislav Marohnić" /></a><a href="https://github.com/aexvir"><img src="https://github.com/aexvir.png" width="60px" alt="Alex Viscreanu" /></a><a href="https://github.com/dbalatero"><img src="https://github.com/dbalatero.png" width="60px" alt="David Balatero" /></a><a href="https://github.com/comatory"><img src="https://github.com/comatory.png" width="60px" alt="Ondrej Synacek" /></a><a href="https://github.com/moobar"><img src="https://github.com/moobar.png" width="60px" alt="" /></a><a href="https://github.com/majjoha"><img src="https://github.com/majjoha.png" width="60px" alt="Mathias Jean Johansen" /></a><a href="https://github.com/benelan"><img src="https://github.com/benelan.png" width="60px" alt="Ben Elan" /></a><a href="https://github.com/pawelduda"><img src="https://github.com/pawelduda.png" width="60px" alt="Paweł Duda" /></a><a href="https://github.com/slezica"><img src="https://github.com/slezica.png" width="60px" alt="Santiago Lezica" /></a><a href="https://github.com/pbwn"><img src="https://github.com/pbwn.png" width="60px" alt="" /></a><a href="https://github.com/timgluz"><img src="https://github.com/timgluz.png" width="60px" alt="Timo Sulg" /></a><a href="https://github.com/pyrho"><img src="https://github.com/pyrho.png" width="60px" alt="Damien Rajon" /></a><a href="https://github.com/ArtBIT"><img src="https://github.com/ArtBIT.png" width="60px" alt="ArtBIT" /></a><a href="https://github.com/da-moon"><img src="https://github.com/da-moon.png" width="60px" alt="" /></a><a href="https://github.com/hovissimo"><img src="https://github.com/hovissimo.png" width="60px" alt="Hovis" /></a><a href="https://github.com/dariusjonda"><img src="https://github.com/dariusjonda.png" width="60px" alt="Darius Jonda" /></a><a href="https://github.com/mortymacs"><img src="https://github.com/mortymacs.png" width="60px" alt="Morteza NourelahiAlamdari" /></a><a href="https://github.com/cristiand391"><img src="https://github.com/cristiand391.png" width="60px" alt="Cristian Dominguez" /></a><a href="https://github.com/eliangcs"><img src="https://github.com/eliangcs.png" width="60px" alt="Chang-Hung Liang" /></a><a href="https://github.com/asphaltbuffet"><img src="https://github.com/asphaltbuffet.png" width="60px" alt="Ben Lechlitner" /></a><a href="https://github.com/yash1th"><img src="https://github.com/yash1th.png" width="60px" alt="yash" /></a><a href="https://github.com/looshch"><img src="https://github.com/looshch.png" width="60px" alt="george looshch" /></a><a href="https://github.com/kg8m"><img src="https://github.com/kg8m.png" width="60px" alt="Takumi KAGIYAMA" /></a><a href="https://github.com/polm"><img src="https://github.com/polm.png" width="60px" alt="Paul O'Leary McCann" /></a><a href="https://github.com/rbeeger"><img src="https://github.com/rbeeger.png" width="60px" alt="Robert Beeger" /></a><a href="https://github.com/veebch"><img src="https://github.com/veebch.png" width="60px" alt="gmail" /></a><a href="https://github.com/khuedoan"><img src="https://github.com/khuedoan.png" width="60px" alt="Khue Doan" /></a><a href="https://github.com/yowayb"><img src="https://github.com/yowayb.png" width="60px" alt="Yoway Buorn" /></a><a href="https://github.com/scalisi"><img src="https://github.com/scalisi.png" width="60px" alt="Josh Scalisi" /></a><a href="https://github.com/alecbcs"><img src="https://github.com/alecbcs.png" width="60px" alt="Alec Scott" /></a><a href="https://github.com/thnxdev"><img src="https://github.com/thnxdev.png" width="60px" alt="thanks.dev" /></a><a href="https://github.com/artursapek"><img src="https://github.com/artursapek.png" width="60px" alt="Artur Sapek" /></a><a href="https://github.com/ramnes"><img src="https://github.com/ramnes.png" width="60px" alt="Guillaume Gelin" /></a><a href="https://github.com/jyc"><img src="https://github.com/jyc.png" width="60px" alt="" /></a><a href="https://github.com/mrcnski"><img src="https://github.com/mrcnski.png" width="60px" alt="Marcin S." /></a><a href="https://github.com/roblevy"><img src="https://github.com/roblevy.png" width="60px" alt="Rob Levy" /></a><a href="https://github.com/michael-dwan"><img src="https://github.com/michael-dwan.png" width="60px" alt="Michael Dwan" /></a><a href="https://github.com/glozow"><img src="https://github.com/glozow.png" width="60px" alt="Gloria Zhao" /></a><!-- sponsors -->
 
 Table of Contents
 -----------------
@@ -212,9 +230,9 @@ selected item to STDOUT.
 find * -type f | fzf > selected
 ```
 
-Without STDIN pipe, fzf will use find command to fetch the list of
-files excluding hidden ones. (You can override the default command with
-`FZF_DEFAULT_COMMAND`)
+Without STDIN pipe, fzf will traverse the file system under the current
+directory to get the list of files, skipping hidden directories. (You can
+override the default behavior with `FZF_DEFAULT_COMMAND`)
 
 ```sh
 vim $(fzf)
@@ -311,6 +329,10 @@ or `py`.
 - `FZF_DEFAULT_OPTS`
     - Default options
     - e.g. `export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"`
+- `FZF_DEFAULT_OPTS_FILE`
+    - If you prefer to manage default options in a file, set this variable to
+      point to the location of the file
+    - e.g. `export FZF_DEFAULT_OPTS_FILE=~/.fzfrc`
 
 ### Options
 
@@ -470,8 +492,7 @@ export FZF_COMPLETION_TRIGGER='~~'
 # Options to fzf command
 export FZF_COMPLETION_OPTS='--border --info=inline'
 
-# Use fd (https://github.com/sharkdp/fd) instead of the default find
-# command for listing path candidates.
+# Use fd (https://github.com/sharkdp/fd) for listing path candidates.
 # - The first argument to the function ($1) is the base path to start traversal
 # - See the source code (completion.{bash,zsh}) for the details.
 _fzf_compgen_path() {
@@ -756,9 +777,8 @@ Tips
 
 You can use [fd](https://github.com/sharkdp/fd),
 [ripgrep](https://github.com/BurntSushi/ripgrep), or [the silver
-searcher](https://github.com/ggreer/the_silver_searcher) instead of the
-default find command to traverse the file system while respecting
-`.gitignore`.
+searcher](https://github.com/ggreer/the_silver_searcher) to traverse the file
+system while respecting `.gitignore`.
 
 ```sh
 # Feed the output of fd into fzf
diff --git a/bin/fzf-tmux b/bin/fzf-tmux
index 003fbdb1..c41e755e 100755
--- a/bin/fzf-tmux
+++ b/bin/fzf-tmux
@@ -95,9 +95,9 @@ while [[ $# -gt 0 ]]; do
       elif [[ "$size" =~ %$ ]]; then
         size=${size:0:((${#size}-1))}
         if [[ -n "$swap" ]]; then
-          opt="$opt -p $(( 100 - size ))"
+          opt="$opt -l $(( 100 - size ))%"
         else
-          opt="$opt -p $size"
+          opt="$opt -l $size%"
         fi
       else
         if [[ -n "$swap" ]]; then
diff --git a/doc/fzf.txt b/doc/fzf.txt
index 607637e7..cf8c6af3 100644
--- a/doc/fzf.txt
+++ b/doc/fzf.txt
@@ -1,4 +1,4 @@
-fzf.txt	fzf	Last change: January 1 2024
+fzf.txt	fzf	Last change: February 15 2024
 FZF - TABLE OF CONTENTS                                            *fzf* *fzf-toc*
 ==============================================================================
 
@@ -264,17 +264,18 @@ entry.
     call fzf#run({'sink': 'e'})
 <
 We haven't specified the `source`, so this is equivalent to starting fzf on
-command line without standard input pipe; fzf will use find command (or
-`$FZF_DEFAULT_COMMAND` if defined) to list the files under the current
-directory. When you select one, it will open it with the sink, `:e` command.
-If you want to open it in a new tab, you can pass `:tabedit` command instead
-as the sink.
+command line without standard input pipe; fzf will traverse the file system
+under the current directory to get the list of files. (If
+`$FZF_DEFAULT_COMMAND` is set, fzf will use the output of the command
+instead.) When you select one, it will open it with the sink, `:e` command. If
+you want to open it in a new tab, you can pass `:tabedit` command instead as
+the sink.
 >
     call fzf#run({'sink': 'tabedit'})
 <
-Instead of using the default find command, you can use any shell command as
-the source. The following example will list the files managed by git. It's
-equivalent to running `git ls-files | fzf` on shell.
+You can use any shell command as the source to generate the list. The
+following example will list the files managed by git. It's equivalent to
+running `git ls-files | fzf` on shell.
 >
     call fzf#run({'source': 'git ls-files', 'sink': 'e'})
 <
@@ -417,24 +418,12 @@ TIPS                                                                  *fzf-tips*
 < fzf inside terminal buffer >________________________________________________~
                                                     *fzf-inside-terminal-buffer*
 
-The latest versions of Vim and Neovim include builtin terminal emulator
-(`:terminal`) and fzf will start in a terminal buffer in the following cases:
-
- - On Neovim
- - On GVim
- - On Terminal Vim with a non-default layout
-   - `call fzf#run({'left': '30%'})` or `let g:fzf_layout = {'left': '30%'}`
 
 On the latest versions of Vim and Neovim, fzf will start in a terminal buffer.
 If you find the default ANSI colors to be different, consider configuring the
 colors using `g:terminal_ansi_colors` in regular Vim or `g:terminal_color_x`
 in Neovim.
 
-                   *g:terminal_color_15* *g:terminal_color_14* *g:terminal_color_13*
-*g:terminal_color_12* *g:terminal_color_11* *g:terminal_color_10* *g:terminal_color_9*
-   *g:terminal_color_8* *g:terminal_color_7* *g:terminal_color_6* *g:terminal_color_5*
-   *g:terminal_color_4* *g:terminal_color_3* *g:terminal_color_2* *g:terminal_color_1*
-                                                            *g:terminal_color_0*
 >
     " Terminal colors for seoul256 color scheme
     if has('nvim')
diff --git a/go.mod b/go.mod
index ebdad5fa..622d677b 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
 module github.com/junegunn/fzf
 
 require (
-	github.com/gdamore/tcell/v2 v2.7.0
-	github.com/mattn/go-isatty v0.0.17
+	github.com/charlievieth/fastwalk v1.0.2
+	github.com/gdamore/tcell/v2 v2.7.1
+	github.com/mattn/go-isatty v0.0.20
 	github.com/mattn/go-shellwords v1.0.12
 	github.com/rivo/uniseg v0.4.7
-	github.com/saracen/walker v0.1.3
 	golang.org/x/sys v0.17.0
 	golang.org/x/term v0.17.0
 )
@@ -14,7 +14,6 @@ require (
 	github.com/gdamore/encoding v1.0.0 // indirect
 	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
 	github.com/mattn/go-runewidth v0.0.15 // indirect
-	golang.org/x/sync v0.5.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 )
 
diff --git a/go.sum b/go.sum
index 6d6dab26..45a31f0f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,11 +1,13 @@
+github.com/charlievieth/fastwalk v1.0.2 h1:KYWo7xszmoldOGrwdNIeznSzhj9mhgk+6DwHunG99bc=
+github.com/charlievieth/fastwalk v1.0.2/go.mod h1:JSfglY/gmL/rqsUS1NCsJTocB5n6sSl9ApAqif4CUbs=
 github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
 github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
-github.com/gdamore/tcell/v2 v2.7.0 h1:I5LiGTQuwrysAt1KS9wg1yFfOI3arI3ucFrxtd/xqaA=
-github.com/gdamore/tcell/v2 v2.7.0/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
+github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc=
+github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
 github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
@@ -14,8 +16,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
 github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
-github.com/saracen/walker v0.1.3 h1:YtcKKmpRPy6XJTHJ75J2QYXXZYWnZNQxPCVqZSHVV/g=
-github.com/saracen/walker v0.1.3/go.mod h1:FU+7qU8DeQQgSZDmmThMJi93kPkLFgy0oVAcLxurjIk=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -26,25 +26,20 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
 golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index c10f334e..76bfa648 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -865,7 +865,14 @@ with \fB$SHELL -c\fR if \fBSHELL\fR is set, otherwise with \fBsh -c\fR, so in
 this case make sure that the command is POSIX-compliant.
 .TP
 .B FZF_DEFAULT_OPTS
-Default options. e.g. \fBexport FZF_DEFAULT_OPTS="--extended --cycle"\fR
+Default options.
+.br
+e.g. \fBexport FZF_DEFAULT_OPTS="--layout=reverse --border --cycle"\fR
+.TP
+.B FZF_DEFAULT_OPTS_FILE
+The location of the file that contains the default options.
+.br
+e.g. \fBexport FZF_DEFAULT_OPTS_FILE=~/.fzfrc\fR
 .TP
 .B FZF_API_KEY
 Can be used to require an API key when using \fB--listen\fR option. If not set,
diff --git a/src/algo/algo.go b/src/algo/algo.go
index 1d021ed0..5cb82bdd 100644
--- a/src/algo/algo.go
+++ b/src/algo/algo.go
@@ -255,24 +255,29 @@ func charClassOf(char rune) charClass {
 
 func bonusFor(prevClass charClass, class charClass) int16 {
 	if class > charNonWord {
-		if prevClass == charWhite {
+		switch prevClass {
+		case charWhite:
 			// Word boundary after whitespace
 			return bonusBoundaryWhite
-		} else if prevClass == charDelimiter {
+		case charDelimiter:
 			// Word boundary after a delimiter character
 			return bonusBoundaryDelimiter
-		} else if prevClass == charNonWord {
+		case charNonWord:
 			// Word boundary
 			return bonusBoundary
 		}
 	}
+
 	if prevClass == charLower && class == charUpper ||
 		prevClass != charNumber && class == charNumber {
 		// camelCase letter123
 		return bonusCamel123
-	} else if class == charNonWord {
+	}
+
+	switch class {
+	case charNonWord, charDelimiter:
 		return bonusNonWord
-	} else if class == charWhite {
+	case charWhite:
 		return bonusBoundaryWhite
 	}
 	return 0
diff --git a/src/constants.go b/src/constants.go
index 76211dcd..f5f8a939 100644
--- a/src/constants.go
+++ b/src/constants.go
@@ -2,7 +2,6 @@ package fzf
 
 import (
 	"math"
-	"os"
 	"time"
 
 	"github.com/junegunn/fzf/src/util"
@@ -54,16 +53,6 @@ const (
 	defaultJumpLabels string = "asdfghjklqwertyuiopzxcvbnm1234567890ASDFGHJKLQWERTYUIOPZXCVBNM`~;:,<.>/?'\"!@#$%^&*()[{]}-_=+"
 )
 
-var defaultCommand string
-
-func init() {
-	if !util.IsWindows() {
-		defaultCommand = `set -o pipefail; command find -L . -mindepth 1 \( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \) -prune -o -type f -print -o -type l -print 2> /dev/null | cut -b3-`
-	} else if os.Getenv("TERM") == "cygwin" {
-		defaultCommand = `sh -c "command find -L . -mindepth 1 -path '*/.*' -prune -o -type f -print -o -type l -print 2> /dev/null | cut -b3-"`
-	}
-}
-
 // fzf events
 const (
 	EvtReadNew util.EventType = iota
diff --git a/src/core.go b/src/core.go
index ed56a879..56a2198e 100644
--- a/src/core.go
+++ b/src/core.go
@@ -213,6 +213,7 @@ func Run(opts *Options, version string, revision string) {
 	reading := true
 	ticks := 0
 	var nextCommand *string
+	var nextEnviron []string
 	eventBox.Watch(EvtReadNew)
 	total := 0
 	query := []rune{}
@@ -232,13 +233,13 @@ func Run(opts *Options, version string, revision string) {
 	useSnapshot := false
 	var snapshot []*Chunk
 	var count int
-	restart := func(command string) {
+	restart := func(command string, environ []string) {
 		reading = true
 		chunkList.Clear()
 		itemIndex = 0
 		inputRevision++
 		header = make([]string, 0, opts.HeaderLines)
-		go reader.restart(command)
+		go reader.restart(command, environ)
 	}
 	for {
 		delay := true
@@ -266,8 +267,9 @@ func Run(opts *Options, version string, revision string) {
 					os.Exit(value.(int))
 				case EvtReadNew, EvtReadFin:
 					if evt == EvtReadFin && nextCommand != nil {
-						restart(*nextCommand)
+						restart(*nextCommand, nextEnviron)
 						nextCommand = nil
+						nextEnviron = nil
 						break
 					} else {
 						reading = reading && evt == EvtReadNew
@@ -292,11 +294,13 @@ func Run(opts *Options, version string, revision string) {
 
 				case EvtSearchNew:
 					var command *string
+					var environ []string
 					var changed bool
 					switch val := value.(type) {
 					case searchRequest:
 						sort = val.sort
 						command = val.command
+						environ = val.environ
 						changed = val.changed
 						if command != nil {
 							useSnapshot = val.sync
@@ -306,8 +310,9 @@ func Run(opts *Options, version string, revision string) {
 						if reading {
 							reader.terminate()
 							nextCommand = command
+							nextEnviron = environ
 						} else {
-							restart(*command)
+							restart(*command, environ)
 						}
 					}
 					if !changed {
diff --git a/src/options.go b/src/options.go
index dcb70dcb..09787a44 100644
--- a/src/options.go
+++ b/src/options.go
@@ -126,8 +126,8 @@ const usage = `usage: fzf [options]
 
   Environment variables
     FZF_DEFAULT_COMMAND    Default command to use when input is tty
-    FZF_DEFAULT_OPTS       Default options
-                           (e.g. '--layout=reverse --inline-info')
+    FZF_DEFAULT_OPTS       Default options (e.g. '--layout=reverse --info=inline')
+    FZF_DEFAULT_OPTS_FILE  Location of the file to read default options from
     FZF_API_KEY            X-API-Key header for HTTP server (--listen)
 
 `
@@ -421,8 +421,10 @@ func help(code int) {
 	os.Exit(code)
 }
 
+var errorContext = ""
+
 func errorExit(msg string) {
-	os.Stderr.WriteString(msg + "\n")
+	os.Stderr.WriteString(errorContext + msg + "\n")
 	os.Exit(exitError)
 }
 
@@ -2167,13 +2169,36 @@ func ParseOptions() *Options {
 		}
 	}
 
-	// Options from Env var
-	words, _ := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
+	// 1. Options from $FZF_DEFAULT_OPTS_FILE
+	if path := os.Getenv("FZF_DEFAULT_OPTS_FILE"); path != "" {
+		bytes, err := os.ReadFile(path)
+		if err != nil {
+			errorContext = "$FZF_DEFAULT_OPTS_FILE: "
+			errorExit(err.Error())
+		}
+
+		words, parseErr := shellwords.Parse(string(bytes))
+		if parseErr != nil {
+			errorContext = path + ": "
+			errorExit(parseErr.Error())
+		}
+		if len(words) > 0 {
+			parseOptions(opts, words)
+		}
+	}
+
+	// 2. Options from $FZF_DEFAULT_OPTS string
+	words, parseErr := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
+	errorContext = "$FZF_DEFAULT_OPTS: "
+	if parseErr != nil {
+		errorExit(parseErr.Error())
+	}
 	if len(words) > 0 {
 		parseOptions(opts, words)
 	}
 
-	// Options from command-line arguments
+	// 3. Options from command-line arguments
+	errorContext = ""
 	parseOptions(opts, os.Args[1:])
 
 	postProcessOptions(opts)
diff --git a/src/reader.go b/src/reader.go
index 494a2f72..fb45c7b9 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -6,14 +6,13 @@ import (
 	"io"
 	"os"
 	"os/exec"
-	"path"
 	"path/filepath"
 	"sync"
 	"sync/atomic"
 	"time"
 
+	"github.com/charlievieth/fastwalk"
 	"github.com/junegunn/fzf/src/util"
-	"github.com/saracen/walker"
 )
 
 // Reader reads from command or standard input
@@ -77,20 +76,19 @@ func (r *Reader) fin(success bool) {
 
 func (r *Reader) terminate() {
 	r.mutex.Lock()
-	defer func() { r.mutex.Unlock() }()
-
 	r.killed = true
 	if r.exec != nil && r.exec.Process != nil {
 		util.KillCommand(r.exec)
-	} else if defaultCommand != "" {
+	} else {
 		os.Stdin.Close()
 	}
+	r.mutex.Unlock()
 }
 
-func (r *Reader) restart(command string) {
+func (r *Reader) restart(command string, environ []string) {
 	r.event = int32(EvtReady)
 	r.startEventPoller()
-	success := r.readFromCommand(nil, command)
+	success := r.readFromCommand(command, environ)
 	r.fin(success)
 }
 
@@ -99,26 +97,12 @@ func (r *Reader) ReadSource() {
 	r.startEventPoller()
 	var success bool
 	if util.IsTty() {
-		// The default command for *nix requires a shell that supports "pipefail"
-		// https://unix.stackexchange.com/a/654932/62171
-		shell := "bash"
-		currentShell := os.Getenv("SHELL")
-		currentShellName := path.Base(currentShell)
-		for _, shellName := range []string{"bash", "zsh", "ksh", "ash", "hush", "mksh", "yash"} {
-			if currentShellName == shellName {
-				shell = currentShell
-				break
-			}
-		}
 		cmd := os.Getenv("FZF_DEFAULT_COMMAND")
 		if len(cmd) == 0 {
-			if defaultCommand != "" {
-				success = r.readFromCommand(&shell, defaultCommand)
-			} else {
-				success = r.readFiles()
-			}
+			success = r.readFiles()
 		} else {
-			success = r.readFromCommand(nil, cmd)
+			// We can't export FZF_* environment variables to the default command
+			success = r.readFromCommand(cmd, nil)
 		}
 	} else {
 		success = r.readFromStdin()
@@ -163,10 +147,14 @@ func (r *Reader) readFromStdin() bool {
 
 func (r *Reader) readFiles() bool {
 	r.killed = false
-	fn := func(path string, mode os.FileInfo) error {
+	conf := fastwalk.Config{Follow: true}
+	fn := func(path string, de os.DirEntry, err error) error {
+		if err != nil {
+			return nil
+		}
 		path = filepath.Clean(path)
 		if path != "." {
-			isDir := mode.Mode().IsDir()
+			isDir := de.IsDir()
 			if isDir && filepath.Base(path)[0] == '.' {
 				return filepath.SkipDir
 			}
@@ -181,20 +169,16 @@ func (r *Reader) readFiles() bool {
 		}
 		return nil
 	}
-	cb := walker.WithErrorCallback(func(pathname string, err error) error {
-		return nil
-	})
-	return walker.Walk(".", fn, cb) == nil
+	return fastwalk.Walk(&conf, ".", fn) == nil
 }
 
-func (r *Reader) readFromCommand(shell *string, command string) bool {
+func (r *Reader) readFromCommand(command string, environ []string) bool {
 	r.mutex.Lock()
 	r.killed = false
 	r.command = &command
-	if shell != nil {
-		r.exec = util.ExecCommandWith(*shell, command, true)
-	} else {
-		r.exec = util.ExecCommand(command, true)
+	r.exec = util.ExecCommand(command, true)
+	if environ != nil {
+		r.exec.Env = environ
 	}
 	out, err := r.exec.StdoutPipe()
 	if err != nil {
diff --git a/src/terminal.go b/src/terminal.go
index b38a0629..2069571a 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -67,7 +67,7 @@ func init() {
 	// * https://sw.kovidgoyal.net/kitty/graphics-protocol
 	// * https://en.wikipedia.org/wiki/Sixel
 	// * https://iterm2.com/documentation-images.html
-	passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?\a`)
+	passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?(\a|\x1b\\)`)
 }
 
 type jumpMode int
@@ -499,6 +499,7 @@ type searchRequest struct {
 	sort    bool
 	sync    bool
 	command *string
+	environ []string
 	changed bool
 }
 
@@ -4081,10 +4082,15 @@ func (t *Terminal) Loop() {
 			req(reqPrompt)
 		}
 
+		reload := changed || newCommand != nil
+		var reloadRequest *searchRequest
+		if reload {
+			reloadRequest = &searchRequest{sort: t.sort, sync: reloadSync, command: newCommand, environ: t.environ(), changed: changed}
+		}
 		t.mutex.Unlock() // Must be unlocked before touching reqBox
 
-		if changed || newCommand != nil {
-			t.eventBox.Set(EvtSearchNew, searchRequest{sort: t.sort, sync: reloadSync, command: newCommand, changed: changed})
+		if reload {
+			t.eventBox.Set(EvtSearchNew, *reloadRequest)
 		}
 		for _, event := range events {
 			t.reqBox.Set(event, nil)


Test patch:
diff --git a/src/reader_test.go b/src/reader_test.go
index feb45fc5..bf06fd09 100644
--- a/src/reader_test.go
+++ b/src/reader_test.go
@@ -22,7 +22,7 @@ func TestReadFromCommand(t *testing.T) {
 	}
 
 	// Normal command
-	reader.fin(reader.readFromCommand(nil, `echo abc&&echo def`))
+	reader.fin(reader.readFromCommand(`echo abc&&echo def`, nil))
 	if len(strs) != 2 || strs[0] != "abc" || strs[1] != "def" {
 		t.Errorf("%s", strs)
 	}
@@ -47,7 +47,7 @@ func TestReadFromCommand(t *testing.T) {
 	reader.startEventPoller()
 
 	// Failing command
-	reader.fin(reader.readFromCommand(nil, `no-such-command`))
+	reader.fin(reader.readFromCommand(`no-such-command`, nil))
 	strs = []string{}
 	if len(strs) > 0 {
 		t.Errorf("%s", strs)
diff --git a/test/test_go.rb b/test/test_go.rb
index 0f7e3045..599d5442 100755
--- a/test/test_go.rb
+++ b/test/test_go.rb
@@ -1918,7 +1918,7 @@ class TestGoFZF < TestBase
   end
 
   def test_reload
-    tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:reload(seq {q}),a:reload(seq 100),b:reload:seq 200' --header-lines 2 --multi 2), :Enter
+    tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:reload(seq $FZF_QUERY),a:reload(seq 100),b:reload:seq 200' --header-lines 2 --multi 2), :Enter
     tmux.until { |lines| assert_equal 998, lines.match_count }
     tmux.send_keys 'a'
     tmux.until do |lines|
@@ -2582,6 +2582,7 @@ class TestGoFZF < TestBase
   def test_change_preview_window_rotate
     tmux.send_keys "seq 100 | #{FZF} --preview-window left,border-none --preview 'echo hello' --bind '" \
       "a:change-preview-window(right|down|up|hidden|)'", :Enter
+    tmux.until { |lines| assert(lines.any? { _1.include?('100/100') }) }
     3.times do
       tmux.until { |lines| lines[0].start_with?('hello') }
       tmux.send_keys 'a'