On 26 March 2026 at 18:35:11 I typed something completely boring:
find engine -maxdepth 3 -type f | sort
And got an error I didn’t understand.
Not a permission denied. Not a “no such file”. Just… the wrong tool talking back. The command I typed had stopped being find months earlier, and I’d forgotten. My own clever hijack had eaten the one moment I actually needed the original.
Twenty-two seconds later I tried it again with double dashes. Another error. At 18:35:57 — forty-six seconds after I started — I gave up and just cd engine instead.
That’s the whole story, really. The rest is me refusing to let it happen twice. 😅
The Diagnosis: Who Is Actually Running? 🔍
The first move when your shell lies to you is to ask it directly:
type -a find
Which on my machine returns:
find is a function with definition
# Defined in /home/bitzy/.config/fish/functions/find.fish @ line 1
function find --wraps=fd --description 'alias find fd'
fd $argv
end
find is /usr/bin/find
Read that twice.
There are two finds. The function wins — it always wins, because fish looks up functions before it ever reaches PATH. And the function doesn’t call GNU find. It calls fd, and hands it every argument I typed, unchanged.
So when I type find …, the thing that actually runs is:
function find --wraps=fd --description 'alias find fd'
fd $argv
end
Seven words of shell, written by Past Me on 4 January 2026 at 16:49:36 — the same afternoon I installed fd-find and got excited about it.
My history even remembers the moment I fell in love:
2026-01-04 16:28:14 sudo dnf install eza fd-find fzf
2026-01-04 16:33:22 fdfind
2026-01-04 16:33:59 alias find fd
2026-01-04 16:49:36 alias -s find fd
Nineteen minutes from install to “I’m wiring this over the top of everything.” No hesitation whatsoever.
Why It Broke: Two Tools, Two Dialects 🗣️
Here’s the part that took me longer than it should have.
find and fd do not speak the same flag language. They solve the same problem, but they spell their options completely differently:
| Job | GNU find | fd |
|---|---|---|
| How deep | -maxdepth 3 | -d 3 or --max-depth 3 |
| File type | -type f | -t file |
Notice fd wants --max-depth — with a hyphen — and -t file, not -type f.
So my hijack takes a sentence written in GNU find grammar and feeds it to a tool that’s never heard of it. Here’s what actually happens, tested just now:
My original command, through the hijack:
$ find engine -maxdepth 1 -type f
error: unexpected argument '-m' found
tip: to pass '-m' as a value, use '-- -m'
fd doesn’t have a -m. It saw -maxdepth, grabbed the first letter, shrugged, and died.
And the same command with the real find:
$ command find engine -maxdepth 1 -type f
engine/a.txt
Works perfectly. Because that’s the syntax it was written for.
The Honest Bit: My Retry Was Wrong Too 🤦
Now here’s where I have to be honest with you, because it’s funnier than pretending otherwise.
My second attempt, twenty-two seconds after the first, was:
find engine --maxdepth 3 --type f | sort
I’d thrown extra dashes on, the way you do when something’s not working. And it failed too — but for a different reason on each side:
$ find engine --maxdepth 1 -type f # through the hijack (fd)
error: invalid value 'ype' for '--type <filetype>'
[possible values: file, directory, symlink, …]
fd split -type into -t plus the value ype. ype is not a file type. Wonderful.
$ command find engine --maxdepth 1 -type f # the real GNU find
find: unknown predicate `--maxdepth'
The real find rejected my retry too. GNU findutils wants -maxdepth — one dash. My “fix” was wrong for both tools.
So that forty-six seconds in March? It wasn’t recoverable by trying harder. The escape hatch I needed only works if you use the right language when you get there.
The Exit Doors (Only Two, And I Checked) 🚪
Every hijack needs a way out. I tested all the candidates on this machine — and I’m only listing the ones that actually worked:
✅ command — the reliable one:
$ command find --version
find (GNU findutils) 4.10.0
command tells fish: “skip the functions, go find the real binary.” It’s the one I’d memorise first.
✅ Absolute path — always works, everywhere:
$ /usr/bin/find --version
find (GNU findutils) 4.10.0
Ugly, verbose, and completely unambiguous. /usr/bin/find is sitting right there, untouched, 213,448 bytes of pure GNU findutils.
❌ And no, the backslash trick does not work in fish.
I’d seen \command escapes suggested in a few places and assumed \find would bypass the function. It doesn’t. Here’s the raw error:
$ \find --version
fish: Unknown command: \clind
\find --version
^~~~^
(Exit code 127, by the way. No output. It’s not “nearly working” — it’s dead.)
I’m listing this specifically because I nearly wrote it up as the clever option. Test your escape hatches before you publish them. 😬
Windows Ghosts In The Room 👻
If you’re coming from Windows, you already know this trick — you’ve just never seen it in a text file before.
That find.fish file is an AutoHotkey remap that happens to live in a shell. It’s the same move as rebinding a key so one app stops getting the key it expects, and it’s exactly the same move as dropping a .bat file at the front of PATH to shadow a system binary.
Past Me did this on Windows for years. The difference is that Windows made it a hunt through registry keys and %PATH% ordering, and fish made it one file you can actually read:
~/.config/fish/functions/find.fish
Which is either a point in Linux’s favour, or an argument that I’ve simply moved the same hijacking habit to a nicer neighbourhood. I’ll let you decide. 🙃
The House Rule 📜
Don’t fight habits — hijack them. That was the bet I made back in Supercharging My Fedora 43 Terminal, and I still stand by it. My fingers still type ls and find like a twenty-year Windows/Unix hybrid, and 99% of the time the modern tool underneath gives me a better result for the same keystrokes.
But March taught me the footnote:
Hijack your habits — but always keep an exit door.
Three things I changed after that afternoon:
type -a <command>is now the first thing I reach for when a command behaves strangely. It shows you every version the shell knows about, in resolution order.command <cmd>is memorised. It’s the shortest exit door there is.- My hijacks now get a deliberate companion rather than relying on remembering an escape hatch in a hurry.
The alias stayed, by the way. I’m not undoing months of fd muscle memory over one bad minute — I’m just no longer pretending there’s only one find on this machine.
Add These To The Cheat Sheet 📋
These go straight into the running Fedora cheat sheet, which promised it would keep growing:
| Command | What it’s for |
|---|---|
type -a find | Show every definition of a name, in resolution order |
command find … | Run the real binary, bypassing any function or alias |
/usr/bin/find | The guaranteed escape — full path, no ambiguity |
fd -d <n> | fd’s own depth limit (vs find’s -maxdepth) |
fd -t <type> | fd’s file-type filter (vs find’s -type f) |
So: same keystrokes, better terminal — plus a way out when the better tool doesn’t speak your language.
That’s the deal you make with your own aliases. Still typing find like a Windows power user who never bothered learning the new flags — just this time with a map out. 😄
Ever had a command quietly become something else under you? Drop a comment below — I can’t be the only one. 👇