5 zsh features that make bash feel broken

·cheatly.dev

If you're still on bash because "it works fine," these five zsh features might change your mind. They're not plugins or fancy configs — they're built into zsh and work out of the box.

1. Recursive globbing

Find all Python files in any subdirectory:

ls **/*.py

In bash, you'd need find . -name "*.py". In zsh, ** just works. It recurses into every subdirectory. Combine it with other globs:

ls **/*.test.{ts,tsx}      # all test files, .ts or .tsx
rm **/*.log                # delete all log files, everywhere
zsh globbing goes further with qualifiers. ls **/*(.) lists only files (not directories). ls **/*(.m-7) lists files modified in the last 7 days. It's like find built into your glob syntax.

2. Auto-cd

Type a directory name and hit Enter — no cd needed:

setopt AUTO_CD

Now ~/projects/cheatly is the same as cd ~/projects/cheatly. Type .. to go up one level. Type ... to go up two. Once you get used to this, typing cd feels like unnecessary ceremony.

3. Suffix aliases

Open files with the right program based on their extension:

alias -s md=nvim
alias -s json=jq .
alias -s py=python3

Now typing README.md opens it in Neovim. Typing data.json pretty-prints it with jq. The file extension becomes the command.

4. History substring search

Add this to your .zshrc:

bindkey '^[[A' history-beginning-search-backward
bindkey '^[[B' history-beginning-search-forward

Now type git and press Up — it only shows commands that started with git. In bash, Up arrow cycles through everything regardless of what you've typed. This one feature alone saves minutes every day.

5. Spelling correction

setopt CORRECT

Type gti push and zsh asks: zsh: correct 'gti' to 'git' [nyae]? Press y and it runs the corrected command. It catches typos in commands, not arguments — useful without being annoying.

If you want corrections for arguments too, use setopt CORRECT_ALL. But fair warning — it gets opinionated about filenames and can be more annoying than helpful.

These features work with a bare zsh install — no oh-my-zsh required. For the full reference, see our zsh cheatsheet.