Skip to content
Go back

The Ghost In My .bashrc: The Alias That Points At Nothing 👻

Yesterday’s story was an alias that pointed at the wrong tool — find quietly became fd, and I got an error from a program that at least existed.

Today’s is worse. Today’s alias points at no tool at all.

Open bash — not fish, bash — and try the most ordinary command in the world:

$ bash -ic 'grep --version'
bash: ag: command not found...

grep isn’t grep. It’s not ripgrep, it’s not BSD grep, it’s not even a slightly wrong version of GNU findutils. It’s ag — The Silver Searcher — which is not installed on this machine.

It hasn’t worked for a single day of this computer’s life.


The Line 👻

There it is, plain as day:

# ~/.bashrc, line 29
alias grep='ag'

And the proof:

$ command -v ag
$ rpm -q the_silver_searcher
package the_silver_searcher is not installed

No output from the first command. That’s the signature — command -v printed nothing and exited non-zero. Nothing is there.

So every time I’ve dropped into a bash session and typed grep, I’ve gotten:

bash: ag: command not found...

Not an error about grep. An error about a completely different program that never showed up.


Why It Survived Untouched 🔦

Two reasons, and the second one is the interesting one.

Reason one: I live in fish.

Fish doesn’t read .bashrc. It has its own grep, and fish’s grep works fine:

function grep --wraps=ag --wraps=ripgrep --wraps=rg --description 'alias grep rg'
    rg $argv
end
$ fish -c 'grep -c alias ~/.bashrc'
6

Six matches. Right tool, right answer, no drama. The ghost sat there in a config file I hadn’t opened in months, firing only on the rare occasions I landed in bash.

Reason two: the dead target is also recorded inside the working one.

Look at that fish function again. The first wrap hint is --wraps=ag.

So even in fish, tab-completing grep still advertises a completion for ag — a program that isn’t there. The same wrong assumption got copied into both shells. It just happens to be harmless in one of them.

That’s the thing about ghosts: they propagate. The version that bit me is the only one loud enough to hear.


It Was Never Installed At All 📜

I went digging before writing this, because “I uninstalled it and forgot” and “it was never there” are very different stories.

$ grep -rin "the_silver_searcher" /var/log/dnf*.log*
(no matches)

The dnf logs on this box start at:

2025-12-01T01:26:00+1100 INFO --- logging initialized ---

That’s the fresh Fedora 43 install. And the_silver_searcher doesn’t appear anywhere across them.

So this isn’t a stale alias left over from an uninstall. It’s an alias written for something I apparently never had. Past Me typed alias grep='ag' into .bashrc — a .bashrc last modified 2026-03-26 at 11:28:39 — and ag was never in the room.

Somewhere between reading about The Silver Searcher and actually installing it, the install step got skipped. The alias didn’t.


A Bonus Ghost, Same File 👻👻

Since I had .bashrc open, here’s another line doing absolutely nothing:

# ~/.bashrc, lines 18-25
if [ -d ~/.bashrc.d ]; then
    for rc in ~/.bashrc.d/*; do
        if [ -f "$rc" ]; then
            . "$rc"
        fi
    done
fi
$ ls ~/.bashrc.d
ls: cannot access '/home/bitzy/.bashrc.d': No such file or directory

The directory doesn’t exist, so the if never fires and the loop never runs. It’s the Fedora default block — perfectly correct code, guarding a door that opens onto nothing.

Dead config, but at least it’s quiet about it. 😅


The Two-Minute Alias Audit 🔍

Here’s the thing I actually wanted when I found this: a way to check every alias at once, instead of discovering them one broken command at a time.

for f in ~/.bashrc ~/.bash_profile ~/.profile; do
  [ -r "$f" ] || continue
  grep -ohE "alias +[A-Za-z0-9_.]+=['\"][^ '\"]+" "$f" 2>/dev/null \
  | sed -E "s/^alias +[A-Za-z0-9_.]+=['\"]//" \
  | sort -u \
  | while IFS= read -r t; do
      if ! command -v "$t" >/dev/null 2>&1; then
        printf '  GHOST  %-10s -> %s\n' "$t" "$(basename "$f")"
      fi
    done
done

Run it. On my machine it prints exactly one line:

  GHOST  ag         -> .bashrc

One. And I checked the others — they’re all fine:

  alias cls   -> clear    OK
  alias cat   -> bat      OK
  alias man   -> tldr     OK
  alias grep  -> ag       MISSING

The whole trick is two commands:

Fourteen seconds, and now I know.


Windows Ghosts In The Room 👻

You’ve met this exact ghost on Windows, just in a friendlier costume.

It’s the Start Menu shortcut to a program you uninstalled six months ago. It’s the DOSKEY macro in a batch file calling a tool that got deleted. Windows shows you a polite dialog — “Windows cannot find ‘ag’” — and you click OK and go about your day.

Same failure. Different neighbourhood.

And it loops straight back to yesterday’s post: .bashrc is my AutoHotkey remap file. Yesterday the remap pointed at the wrong key. Today the remap points at a key that doesn’t exist on the board.

Past Me was very confident about both of them. 😄


The House Rule, Extended 📜

Yesterday’s footnote was:

Hijack your habits — but always keep an exit door.

Today’s addition:

And check the door actually leads somewhere.

An alias is a promise your shell keeps on your behalf. find → fd was a promise kept too well — it answered when I wanted the original. grep → ag is a promise you can’t keep at all, because the thing being promised was never bought.

Three things changed after this one:

  1. command -v is now my reflex for anything that behaves strangely. If it prints nothing, you’re not debugging — you’re looking for a ghost.
  2. I finally ran the audit across .bashrc, .bash_profile and .profile in one sweep rather than trusting that “it’s probably fine.”
  3. The stale --wraps=ag hint in fish is on the list to clean up too. It doesn’t break anything — but a ghost you know about is still a ghost.

The alias itself gets one more day of my patience. It’s a one-line fix, and I’d rather publish the story than pretend I’ve never shipped a dead reference. 🙃


Add These To The Cheat Sheet 📋

Straight into the running Fedora cheat sheet, next to yesterday’s type -a row:

CommandWhat it’s for
command -v <name>Is this command real? Prints a path, or nothing at all
aliasEvery alias the current shell has remapped
bash -ic '<cmd>'Test what a command does in bash (not your login shell)
type -a findEvery definition of a name, in resolution order
grep -ohE "alias..." + command -vBulk-scan rc files for aliases pointing nowhere

Two days, two ghosts: one alias that hijacked the wrong tool, one that hijacked a tool that never existed. Neither of them made a sound until I went looking.

That’s the whole trick, really — your shell will never volunteer that it’s lying to you.

Got an alias you’re now afraid to test? Drop a comment below and I’ll commiserate. 👇


Share this post on:

Previous Post
The Day My Own Alias Bit Back: When find ➜ fd Ate a Real Command! 🦷
Next Post
Fedora 43 → 44: 4,646 Packages In Eleven Minutes 🚀