cheat-sheets

Shell Comparison

Side-by-side syntax and guidance for choosing between Bash, Zsh, Fish, Nushell and PowerShell. Read it to translate a command from one shell to another or to decide which shell suits a job; full details are in each shell’s own sheet.

Documentation: Bash Reference Manual, Zsh Manual, Fish Documentation, The Nushell Book, PowerShell Documentation

Bash, Zsh, Fish and PowerShell columns were run on Bash 5.3, Zsh 5.9, fish 4.2.1 and PowerShell 7.6. The Nushell column comes from its documentation and was not run; rows marked (unverified) were not confirmed.

Which Shell #

SHELL | BEST FOR | SCRIPTS PORTABLE? —|— Bash | Servers, scripts, CI, anything others will run | Yes: the de facto standard on Linux Zsh | Interactive use with powerful globbing and completion; macOS default | Mostly Bash-like, with different array and splitting rules Fish | Friendly interactive use with no configuration | No: its own syntax Nushell | Working with structured data (tables, JSON, CSV) in a pipeline | No: its own syntax and still changing between releases PowerShell Cheat-Sheet | Windows administration and anything that returns objects | Cross-platform, but not POSIX-like POSIX sh (dash, BusyBox ash) | Minimal images and scripts that must run anywhere | Yes, with the fewest features; lint with shellcheck -s sh (ShellCheck and shfmt)

A common setup is an interactive shell of your choice with #!/usr/bin/env bash at the top of every script, so scripts behave the same everywhere.

Syntax Side by Side #

TASKBASH AND ZSHFISHNUSHELLPOWERSHELL
Set a variableNAME=valueset NAME valuelet name = "value"$name = "value"
Export / environmentexport NAME=valueset -gx NAME value$env.NAME = "value"$env:NAME = "value"
Command substitution$(cmd)(cmd)(cmd)$(cmd)
Lista=(x y z)set a x y zlet a = [x y z]$a = "x","y","z"
First elementBash ${a[0]}, Zsh $a[1]$a[1]$a.0 (unverified)$a[0]
Last exit status$?$status$env.LAST_EXIT_CODE (external commands)$LASTEXITCODE
All script arguments"$@"$argvdef main [...rest] { }$args
If statementif [[ -f f ]]; then ...; fiif test -f f; ...; endif ("f" | path exists) { ... } (unverified)if (Test-Path f) { ... }
Loopfor i in 1 2 3; do ...; donefor i in 1 2 3; ...; endfor i in 1..3 { ... }foreach ($i in 1..3) { ... }
Functionf() { ...; }function f; ...; enddef f [] { ... }function f { ... }
Run on errorcmd || othercmd; or othertry { cmd } catch { other }try { cmd } catch { other }
Start-up file~/.bashrc, ~/.zshrc~/.config/fish/config.fishconfig nu opens it$PROFILE

Pipelines #

SHELLWHAT FLOWS BETWEEN COMMANDS
Bash, Zsh, FishPlain text (bytes); filter with Grep, AWK, jq
NushellStructured data (tables, records, lists)
PowerShell.NET objects

Mixing models is fine: Nushell and PowerShell both run external programs and capture their text output, and jq still works in Bash, Zsh and Fish for JSON.

Switching Your Login Shell #

COMMANDDESCRIPTION
echo "$SHELL"Login shell of the current user
cat /etc/shellsShells the system allows as login shells
chsh -s "$(command -v zsh)"Change your login shell (replace zsh with fish etc.); log out and in again
command -v bash zsh fish nu pwshWhich of these shells are installed

The shell must be listed in /etc/shells before chsh accepts it. On Debian and Ubuntu these are in the bash, zsh and fish packages; Nushell and PowerShell come from their own project repositories or release downloads (see each project’s install page). Changing the login shell of a service or automation account is rarely a good idea: leave it as bash or sh.

Cross-Shell Tools #

TOOLUSE
Starship PromptOne prompt for every shell
Modern CLI Toolsfzf, zoxide, eza and friends, each with integrations for several shells
tmuxTerminal multiplexer, works with any shell
ShellCheck and shfmtLint and format Bash and POSIX sh (it does not support Fish, Nushell or PowerShell)

See Also #

Search all sheets

Tip: / or Ctrl/Cmd+K to open, Esc to close.