If you spend any real time on Linux or macOS, the shell is where you live. It is the program that reads your commands, interprets them, and talks to the kernel on your behalf. Every time you open a terminal, a shell process starts. Pick the right one and your daily workflow gets faster. Pick the wrong one and you fight your tools instead of getting work done.
I have spent over a decade hopping between shells on production servers, personal workstations, and cloud VMs. This guide covers the eight shells I keep coming back to, what each one does well, and where each one falls short. Versions listed here are current as of early 2026.
1. Bash (Bourne Again Shell)
Latest stable version: 5.2 (with patch releases ongoing)
Default on: Most Linux distributions
Website: gnu.org/software/bash
Bash has been the default login shell on nearly every mainstream Linux distribution for decades. It replaced the original Bourne shell (/bin/sh) and added features like command history, job control, brace expansion, and programmable tab completion. If you write a shell script and expect it to run on any Linux box without extra dependencies, Bash is the safe bet.
Where Bash really shines is in its ecosystem. Thousands of tutorials, Stack Overflow answers, and automation playbooks assume Bash. Your .bashrc file is the central place to set aliases, functions, environment variables, and prompt customization. A typical setup might look like this:
# ~/.bashrc example
export EDITOR=vim
export PATH="$HOME/.local/bin:$PATH"
alias ll='ls -alF'
alias gs='git status'
alias k='kubectl'
# Custom prompt showing user, host, and current directory
PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\$ '
Bash supports arrays, associative arrays (since version 4.0), here-strings, process substitution, and regex matching with the =~ operator. For interactive use, it handles the basics: history search with Ctrl+R, tab completion, and job control with fg/bg. It is not the flashiest shell, but it is the one you can count on being installed everywhere.
Strengths: Universal availability, massive community, well-documented, great for portable scripts.
Weaknesses: No built-in syntax highlighting, tab completion requires manual configuration, scripting syntax can be awkward for string manipulation and arithmetic.
2. Zsh (Z Shell)
Latest stable version: 5.9.x
Default on: macOS (since Catalina 10.15)
Website: zsh.org
Apple switched macOS from Bash to Zsh in 2019, and that move alone pushed millions of developers onto it. But Zsh earned that spot. Its completion system is in a different league compared to Bash. Out of the box, Zsh can complete command flags, remote hostnames, git branches, package names, and more. The completion engine is programmable and deeply extensible.
The real game-changer for most people is Oh My Zsh, a community-driven framework that bundles hundreds of plugins and themes. Installing it takes one command:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
After installation, you enable plugins by editing ~/.zshrc:
# ~/.zshrc
plugins=(git docker kubectl aws terraform zsh-autosuggestions zsh-syntax-highlighting)
ZSH_THEME="agnoster"
source $ZSH/oh-my-zsh.sh
The zsh-autosuggestions plugin shows inline suggestions based on your history as you type. The zsh-syntax-highlighting plugin colors your commands green when valid and red when not. Between these two plugins and the built-in completion system, Zsh becomes a genuinely pleasant interactive experience.
Zsh is also mostly compatible with Bash syntax, so migrating scripts is usually painless. There are differences (word splitting behavior, array indexing starting at 1 instead of 0), but for day-to-day commands, you can switch from Bash to Zsh without relearning anything.
Strengths: Best-in-class completion, huge plugin ecosystem through Oh My Zsh, excellent interactive features, largely Bash-compatible.
Weaknesses: Plugin-heavy setups can slow down shell startup, configuration can become complex, slightly different scripting behavior from Bash can cause subtle bugs.
3. Fish (Friendly Interactive Shell)
Latest stable version: 4.0
Default on: None (manual install required)
Website: fishshell.com
Fish takes a fundamentally different approach: everything should work out of the box with zero configuration. The first time you launch Fish, you get syntax highlighting, autosuggestions from history, tab completions with descriptions, and a colorful prompt. No plugins to install. No dotfiles to edit. It just works.
Install Fish on Ubuntu/Debian and try it immediately:
sudo apt install fish
fish
Fish also has a web-based configuration interface. Run fish_config and a browser tab opens where you can pick colors, set your prompt, review functions, and manage abbreviations. This is unusual for a shell, and it lowers the barrier for people who do not want to hand-edit config files.
The big tradeoff is that Fish is not POSIX-compliant. You cannot paste a Bash one-liner from Stack Overflow and expect it to run. Fish uses its own syntax for conditionals, loops, and variable assignment. For example, setting a variable looks like this:
# Fish syntax (not Bash)
set -gx EDITOR vim
set -gx PATH $HOME/.local/bin $PATH
Fish 4.0, released in late 2025, was a major milestone. The shell was rewritten from C++ to Rust, bringing improved performance and memory safety. The scripting language also received refinements, and the autosuggestion engine became noticeably faster on large history files.
Strengths: Best out-of-the-box experience, excellent autosuggestions and highlighting, web-based config, friendly error messages, now Rust-based.
Weaknesses: Not POSIX-compliant, cannot run standard shell scripts without modification, smaller community than Bash or Zsh.
4. PowerShell
Latest stable version: 7.4.x (PowerShell 7.5 previews available)
Default on: Windows (also runs on Linux and macOS)
Website: github.com/PowerShell/PowerShell
PowerShell started as a Windows-only tool, but the open-source cross-platform version (PowerShell 7.x, built on .NET) runs perfectly well on Linux and macOS. If you manage Azure resources, Microsoft 365, or hybrid Windows/Linux environments, PowerShell is worth learning even if you primarily work on Linux.
The core difference between PowerShell and every other shell on this list is its object-oriented pipeline. Traditional Unix shells pass plain text between commands. PowerShell passes .NET objects. That means when you pipe output from one cmdlet to another, you get structured properties, not strings you have to parse with awk and grep.
Here is a practical example that lists processes using more than 100 MB of memory, sorted by usage:
Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB } | Sort-Object WorkingSet64 -Descending | Select-Object Name, @{N='MemMB';E={[math]::Round($_.WorkingSet64/1MB,1)}}
Install PowerShell on Linux with a single package manager command. On Ubuntu:
sudo apt-get install -y powershell
pwsh
PowerShell also has a module system (the PowerShell Gallery) with thousands of modules for AWS, Azure, VMware, Active Directory, and more. For cloud infrastructure work, it fills a gap that traditional shells struggle with.
Strengths: Object-oriented pipeline, excellent for cloud/Windows administration, strong module ecosystem, cross-platform.
Weaknesses: Verbose syntax, slower startup than native Unix shells, feels alien on Linux if you are used to coreutils, large install footprint due to .NET runtime.
5. Nushell
Latest stable version: 0.101.x
Default on: None (manual install required)
Website: nushell.sh
Nushell is one of the most interesting shells to appear in recent years. Like PowerShell, it passes structured data through pipelines instead of plain text. But unlike PowerShell, Nushell is built in Rust and designed from the ground up for Unix-style workflows. The result is a shell where ls returns a table, not a blob of text.
Run ls in Nushell and you get a proper table with columns for name, type, size, and modified date. You can filter, sort, and transform that table with built-in commands:
# List files larger than 1MB, sorted by size
ls | where size > 1mb | sort-by size | reverse
Nushell natively understands JSON, YAML, TOML, CSV, and SQLite. You can open a JSON file and immediately query it:
# Parse and filter JSON data
open data.json | where status == "active" | select name email
This structured approach eliminates the fragile text parsing that plagues traditional shell scripts. No more piping through grep, awk, sed, and cut to extract a single field from command output. You reference columns by name.
Nushell is still pre-1.0, which means breaking changes happen between releases. The project is moving quickly, and the team has been transparent about what is stable and what is not. I would not use it for production automation scripts yet, but for interactive use and data exploration, it is genuinely excellent.
Strengths: Structured data pipelines, native support for multiple data formats, built in Rust (fast), great for data exploration.
Weaknesses: Pre-1.0 with breaking changes between releases, not POSIX-compliant, small community, limited third-party tool integration compared to Bash.
6. Elvish
Latest stable version: 0.21.x
Default on: None (manual install required)
Website: elv.sh
Elvish is written in Go and tries to be both a good interactive shell and a proper programming language. It has typed variables, first-class functions, namespaces, and exception handling. If the scripting limitations of Bash have ever driven you toward Python for a task that should have been a shell script, Elvish might be what you are looking for.
One unique feature is the built-in file navigator. Press Ctrl+N and you get a filesystem browser right inside your terminal. Elvish also includes a command history browser (Ctrl+R, but with a full-screen interactive UI) and a directory history that lets you jump to recently visited paths.
Here is what variable handling and a simple function look like in Elvish:
# Typed variables and lists in Elvish
var name = "server01"
var ports = [22 80 443]
fn greet {|who|
echo "Hello, "$who
}
greet $name
Elvish ships as a single static binary, making installation straightforward on any system. Just download, place in your PATH, and run. No runtime dependencies, no compilation steps.
Strengths: Typed variables, proper programming language features, built-in navigation UI, single binary install, no runtime dependencies.
Weaknesses: Still pre-1.0, not POSIX-compliant, tiny community, limited plugin ecosystem, documentation can be sparse.
7. Dash (Debian Almquist Shell)
Latest stable version: 0.5.12
Default on: Debian and Ubuntu as /bin/sh
Website: gondor.apana.org.au/~herbert/dash
Dash is the opposite of every modern shell on this list. It has no tab completion, no history search, no syntax highlighting, and no autosuggestions. What it does have is speed. Dash is a minimal POSIX-compliant shell designed for one job: executing shell scripts as fast as possible.
Debian and Ubuntu symlink /bin/sh to Dash instead of Bash. The reason is simple: system boot scripts and package maintainer scripts run hundreds of shell invocations during startup and package installation. Dash starts faster and executes POSIX scripts faster than Bash because it is smaller and does less.
You would never use Dash as your interactive shell. But if you write POSIX-compliant scripts and want them to run as quickly as possible, writing for Dash is the way to go. It also serves as a useful compatibility test. If your script runs under Dash, it is genuinely portable POSIX shell code.
To test a script against Dash explicitly:
dash ./myscript.sh
Strengths: Fastest shell for script execution, strict POSIX compliance, minimal resource usage, ideal for system scripts and containers.
Weaknesses: Unusable as an interactive shell, no modern features whatsoever, no arrays, no advanced string manipulation.
Shell Comparison Table
Here is a side-by-side comparison of all seven shells across the categories that matter most when choosing one:
| Shell | POSIX Compliant | Scripting | Interactive Use | Startup Speed | Learning Curve |
|---|---|---|---|---|---|
| Bash | Mostly (with extensions) | Excellent | Good | Fast | Low |
| Zsh | Mostly (with extensions) | Excellent | Excellent | Medium | Low-Medium |
| Fish | No | Good (own syntax) | Excellent | Fast | Low |
| PowerShell | No | Excellent | Good | Slow | Medium-High |
| Nushell | No | Good (evolving) | Excellent | Fast | Medium |
| Elvish | No | Good | Very Good | Fast | Medium |
| Dash | Yes (strict) | Basic (POSIX only) | Poor | Fastest | Low |
How to Change Your Default Shell
On both Linux and macOS, the chsh command changes your default login shell. Before switching, confirm that your target shell is listed in /etc/shells, which is the system’s list of approved login shells.
First, check what shells are available:
cat /etc/shells
If your desired shell is listed, change to it with chsh. For example, to switch to Zsh:
chsh -s /bin/zsh
For Fish (which is typically installed to /usr/bin/fish):
chsh -s /usr/bin/fish
If the shell you want is not in /etc/shells, you need to add it first. This requires root privileges:
echo /usr/local/bin/nu | sudo tee -a /etc/shells
chsh -s /usr/local/bin/nu
Log out and log back in for the change to take effect. Your new shell will start automatically when you open a terminal. If something goes wrong and you cannot log in, you can usually recover by booting into single-user mode or using a live USB to edit /etc/passwd and change your shell back to /bin/bash.
A safer approach for testing a new shell is to simply run it inside your current session without changing the default:
fish
This launches Fish (or whichever shell you specify) as a child process. Type exit to return to your original shell. I always recommend spending at least a week this way before committing with chsh.
Which Shell for Which Use Case
After years of switching between these shells on production systems and personal machines, here is how I would break down the decision.
For portable scripting
Use Bash. Full stop. If you are writing automation that needs to run on any Linux server, CI/CD runner, or Docker container, Bash is the only shell you can rely on being present. For scripts that are part of system startup or packaging, write POSIX sh and test with Dash to guarantee compatibility.
For daily interactive use on macOS
Use Zsh with Oh My Zsh. It is already your default shell, it has a massive plugin library, and the completion system handles everything from git branches to Kubernetes resources. Add the zsh-autosuggestions and zsh-syntax-highlighting plugins and you have a setup that rivals Fish without leaving the POSIX world.
For developers who hate configuration
Use Fish. If you want autosuggestions, syntax highlighting, and smart completions the moment you install the shell, Fish delivers. Just accept that you will need to translate Bash snippets before running them.
For cloud and Windows administration
Use PowerShell. If your work involves Azure, Microsoft 365, Active Directory, or mixed Linux/Windows environments, PowerShell’s module ecosystem and object pipeline make tasks like bulk user management or resource provisioning far simpler than string-parsing your way through with Bash.
For data wrangling and exploration
Try Nushell. If you regularly parse JSON APIs, CSV exports, or log files, Nushell’s structured pipeline turns what would be a five-command Bash pipe into a single readable line. Keep Bash around for your scripts, but use Nushell for interactive data work.
For scripting purists who want a real language
Look at Elvish. Its typed variables, namespaces, and exception handling bring features you would normally reach for Python to get. It is still a young project, but if you want your shell to be a proper programming environment, Elvish is heading in the right direction.
For containers and minimal environments
Use Dash. In Docker images where every megabyte counts and you just need a shell to run an entrypoint script, Dash is the leanest option. Alpine Linux uses BusyBox ash (which is similar to Dash), and Debian-based images already have Dash as /bin/sh.
Final Thoughts
There is no single best shell. The right choice depends on what you do every day. Most sysadmins I know end up using two: one shell for interactive work (Zsh or Fish) and Bash for writing scripts that need to be portable. That combination covers 95% of real-world needs.
If you are just starting out, stick with Bash until you understand how Unix pipes, redirection, and job control work. Those concepts transfer to every other shell. Once you have that foundation, experiment with Zsh or Fish for your daily terminal sessions. You can always drop back to Bash when you need to write something that runs everywhere.
The shells listed here are all free, all open source, and all actively maintained. Install a few, try them for a week each, and see which one fits how you think. Your shell is the tool you use more than any other. It is worth spending the time to pick the right one.



























































There are wrong command to install powershell on Arch Linux. It shall be pacman -S or using yay/paru.
Snapd is default in Ubuntu.
Thank you!
Your method to switch user shell is wrong. You shouldn’t “exec” a shell from `~/.bashrc` file. Use `chsh -s `
For example `chsh /bin/zsh`
This will change the `/etc/passwd` file and set the default shell to the user.