When comparing Bash (Bourne-Again SHell) vs fish (Friendly Interactive SHell), the Slant community recommends fish (Friendly Interactive SHell) for most people. In the question“What are the best UNIX shells?” fish (Friendly Interactive SHell) is ranked 1st while Bash (Bourne-Again SHell) is ranked 3rd. The most important reason people chose fish (Friendly Interactive SHell) is:
fish suggests commands as you type, based on command history, completions, and valid file paths. As you type commands, you will see a completion offered after the cursor, in a muted gray color (which can be changed with the fish_color_autosuggestion variable). However, you can NEVER turn them off!
Ranked in these QuestionsQuestion Ranking
Pros
Pro Default shell on most systems
Bash is the default shell on virtually every UNIX system. Making it very portable across different systems and once you get used to it, you can use it everywhere.
Pro Plenty of examples and tutorials
Since this is very mature shell there is a lot of great examples and other resources describing how to do almost everything.
Pro Rich scripting capabilities on a single line
Want to run something 5 times? Write a throw-away loop: for i in 1 2 3 4 5; do date; done
If you need it 100 times? Not a problem: for i in {1..100}; do date; done
or: for ((i=0; i<100; ++i)); do date; done
How about emailing yourself when remote server is back online? Sure thing: while ! ping -c1 example.com &>/dev/null; do date; sleep 5; done && mailx -s 'server is back!' me@myself.com
Pro POSIX compatible
Pro Emacs-like keyboard control
By default, BASH uses shortcuts and concepts very similar to Emacs, so learning one often results in familiarity with the other.
Pro Rich built-in features
By default, there are many built-in features. They make really complex and reliable programs possible. In comparison to dash, for example, you can do the same tasks in less time and fewer lines of code.
Pro Variables and aliases are listed the way they are built
alias
and set
will list aliases and variables in a format that can be run directly with no modifications. Even if the values contain \n.
This is handy if you want to modify a value.
Pro Recursive globbing
ls **/*.log
for example is supported by Bash if you set shopt -s globstar
.
Pro Man page is a trove of wonders
While the manual "page" is nearly a hundred pages long, it is actually surprisingly succinct and stuffed with good information. It is often better than Googling for answers when writing shell scripts. The way it is written makes it easy to stumble upon useful new programming features just by flipping through it .
NOTE: If you find it dense and hard to read at the command line, look for the PDF version.
Pro vi mode is more comprehensive than on other shells
Vi editing mode works without a glitch. "_" will print you the last argument of the latest command (zsh won't). VI mode is fast off the bat - You don't have to reset any variable (like "KEYTIMEOUT" in zsh) for that.
Pro Copyright license is GPL 3+
Bash is licensed under the GNU General Public License ≥3, which gives much stronger assurances that the right to use it can't be restricted.
For example, Microsoft would not be able to claim in court that, even though they've distributed Bash with the GPLv3, a license that explicitly grants people freedom, now Bash is essentially proprietary due to software patents and everyone who uses Bash owes them money. (This may sound ludicrous to those who were not alive when Microsoft tried a similar scheme against Linux fifteen years ago).
The GPLv3 is a license that reflects the genuine ethical issues that arise when people give their time and skills to collaboratively build software. While most people wouldn't insist that their UNIX shell is licensed under the GPLv3+, it does matter and is a big PRO for Bash.
Pro Built-in 'help'... helps a lot
Built-in 'help' provides quick and efficient help on builtins and keywords.
Pro Rich scripting capabilities
BASH scripting is a rich and robust language.
Pro Auto suggestions
fish suggests commands as you type, based on command history, completions, and valid file paths. As you type commands, you will see a completion offered after the cursor, in a muted gray color (which can be changed with the fish_color_autosuggestion variable). However, you can NEVER turn them off!
Pro Excellent documentation
It has a great tutorial. And the official documentation is clear, full of eloquent examples, and to the point.
Pro Already set up for you
While other shells require a lot of set up to act the way you want them to and to have some useful features, fish works perfectly out of the box. It has all the most widely used features baked in and are there out of the box without having the need to install plugins or tweak any configuration files.
Pro Pretty usable even without plugins
Everything you need from oh-my-zsh is available on default fish, don't need to install any plugins. And even better, fish is smaller than zsh.
Pro Universal variables
You can define Universal variables, which are shared instantaneously through all running fish sessions and persists through shell restarts.
Pro Interactive searchable history
Fish has by far the best way to work with history, everything is automatically searchable. It works in the way you expect. No learning required.
Pro Adding, removing and editing aliases is extremely easy
Pro Creates completion files from manual pages
Fish_update_completions parses manual pages installed on the system, and attempts to create completion files in the fish configuration directory.
Pro Fisherman ⚑ A fast, modern plugin manager for fish
Large test coverage, micro-second shell start, compatibility with plugins from other existing frameworks such as Tackle, Oh My Fish and Wahoo, cache system, offline index, the Fishery and other features.
Pro Intuitive shell expansion in "for" loops
Unlike bash, this won't return you string *.sh if no .sh files are found
for filename in *.sh
echo "$filename"
end
Pro Less ambiguous lists
Here is a sample. Notice that there are 2 files with spaces in names. ls produces a valid list, and for loop correctly iterated through its values.
➤ for a in (ls); ls -l $a; end
-rw-rw-r-- 1 sashka sashka 0 Apr 19 03:16 alma mater.txt
-rw-rw-r-- 1 sashka sashka 0 Apr 19 03:16 whatever i want.txt
sh scripts tend to be fragile when there are lists containing values with spaces.
Also:
➤ echo $PATH
/usr/bin /bin /usr/sbin /sbin /usr/local/bin
➤ echo $PATH[1]
/usr/bin
➤ echo $PATH[-1]
/usr/local/bin
Pro High portability
Because it needs very little configuration to work properly, you can use Fish everywhere. If you are working on a system you don't usually work, installing Fish from the repository is easy and will give you the same experience as the installation on your own machine without having to drag a dotfile around.
Pro Auto indentation when creating functions
When writing functions in an interactive shell, it will auto-indent as needed for if, for, function, etc.
Pro Awesome, consistent, not-confusing sytax
The following, for example:
for file in (find . -name "*.foo" -type f)
fgrep -H "something" $file
echo "hello" $file
end | grep -v "hello"
Will run the for loop, take all the stdout from it (both the fgrep and echo), and then pipe it through the final grep command.
Pro Configuration framework for fish shell
Fish community maintains Oh My Fish, which is a shell framework inspired on Oh My Zsh awesome design and name. It offer a lot of beautiful prompt themes and awesome plugins, is lightweight, awesome and very simple to use.
Cons
Con Extremely complicated and inconsistent rules
In Bash, exceptions are the rule, not even all being described by the main page.
There are a grand total of 5 different ways of quoting, sometimes even when one does not want to, for instance in command substitutions. These are all based around preserving the literal meaning of every character, with an exception list. There is even an exception list to the exception list in 4 of the 5, regarding how the backslash behaves! The behavior of the backslash is also one of the quoting rules, so naturally, it also has an exception in how it works when it stands before a newline as compared to other characters.
Bash has several layers of interpretations, all to be kept in mind:
The ~ expands to the home of the current user. So if you store it in a variable, can you use it that way? Nope: tilde expansion comes before variable expansion.
Aha, so that's how it works! Then, since applying quotation happens after redirections are set up, it must mean that redirecting within quotes works, right? Nope: there is an exception! If a redirection symbol is not quoted, quotation around the symbol is observed, but is not removed. So, since variable expansion also comes after setting up redirections, and no exceptions are described here in the man page, getting the name of a file from a variable and using it as a target should not work, right? No: redirection does not actually take place when the symbols are being read, the symbols are merely removed and are noted for later, right before when the actual command runs.
Apart from 5 types of quotation, there are basically 2 quoting phases, 2 word splitting phases (with only one being controllable), and a tokenization phase on top of that.
If you have a command, it could be an alias, a special built in, a non-special built in, a symbolic link to a file, a regular file, a function, with different rules regarding how they can be overridden, if redirection happens before or after arguments have been passed (what does "time my_command 2>&1 >log_file" do?), etc.
This list is admittedly long, but it doesn't even scratch the surface of the bloat, complexity and inconsistencies of Bash.
Con GPL3 is not compatible with Apple's lawyers
Apple, one of the largest distributors of UNIX systems, only ships an ancient version of bash that predates the iPhone.
No one knows why as Apple hasn't said, but the version Apple includes in MacOS is from right before the license was updated to version 3 of the GNU GPL (General Public License). Other major companies (IBM, Microsoft) have had no problem shipping the latest version of bash
, so it's unclear what Apple's lawyers are averse to. The GPL has always said that if you distributed a program, you granted everyone the right to use it freely. The biggest change in version 3 was the addition, "...and that includes software patents."
This was necessary because back in 2006 Microsoft was demanding that any company that uses Linux pay them or get sued for infringing on their patents. They even took some companies, like TomTom, to court. No software which can be restricted retroactively like that is truly free, so GPL 3+ includes a clause saying that if you distribute the program, then you are also granting license to any patents you own that are necessary to run it.
What patents Apple has that bash could possibly infringe on is a mystery, but the bigger question is, Why does Apple even care? So what if they are granting people the right to run bash without being sued by Apple. It's not like they were planning on doing that, right?
Even though it is not bash's fault that it is not Apple Lawyer-approved, this is a CON for it because a lot of people use Apple products. While there are methods like brew
to install a current version of bash, Apple does not make it obvious to their customers what they are missing.
Con Compatibility can be a curse
One of bash's claims to fame is compatibility with previous versions of itself and historic shells. But, doing that means that new features are often written in tortured, awkward syntax that is not easy to learn. For example, bash uses the POSIX way of doing arithmetic: to add 5+3 you must put the numbers in double parentheses with a dollar sign at the start: x=$((5+3)). It is true that many shells suffer from this same CON, but since bash is such an important shell, it has less wiggleroom to ditch clunky ideas that might break existing scripts.
Con Lags behind on features compared to ZSH and Fish
People who wants power features or to customize their shell experience use zsh or fish.
Con Filename expansion is not consistent
filename expansion is not consistent. "echo *" will print the names of the files in your current dir, if there are any... and will print "*" if there are none.
Con Non-intuitive shell expansion in for loops
If there are no .sh files, this will print mask itself:
for filename in *.sh; do
echo $filename
done
Con No out-of-the-box command autocompletion
To have command autocompletion in bash you need to install third-party plug-ins.
Con One of the most dangerous languages around
What it is mostly used for are file system operations. Guess what it is bad at? Operating on files. It automatically splits and carries out filename expansion on every single string resulting from variable expansion and command substitution unless quoted, by default on whitespace, whilst spaces are very common in filenames.
Before that, it even does pathname expansion, so woe to anywone who does not want to actually operate on files, but has a globbing metacharacter stored anywhere in a variable.
This means what you store in a variable is not going to be what will ACTUALLY be accessed.
If an empty variable is unquoted, it disappears completely due to word splitting, sometimes leading to applications signalling a missing parameter at a wrong position.
If quoted however, said variables cannot be iterated over in a loop, no matter what character one uses for word splitting.
If you use any globbing pattern with a command, be sure to use -- after the option arguments or if none are present, before starting the pattern with a mandatory ./
Otherwise, another Bash script run gone wrong or a hacker can create files named like an option ("-f", for instance) and your program will happily accept it as such, if it results from globbing.
For interactive use, it is convenient. For programming, it is a no-go.
Con Not POSIX compliant
Being POSIX-compliant may be essential to some, but it is not the be-all-and-end-all. Much of the trouble with POSIX-compliant shells is BECAUSE of POSIX, since it captures the poor behavior and syntax that existed. In most cases, POSIX-compliance is a fool's errand since there are significant differences between implementations of even the same shell (e.g., Bash, etc.) on various platforms.
Although fish tries not to break POSIX compatibility without a good reason, and despite efforts to implement a compatibility mechanism, you can face some issues if POSIX compatibility is expected/required.
Though, enthusiasts fix these cases. For example, add
set shell=sh
in your .vimrc to solve the issue for vim.
Con Doesn't support history expansion ("!!")
Fish has no support for !!
, but you can use Oh My Fish shell framework and install bang-bang
plugin to have this shortcut in Fish shell. The downside of using bang-bang is that it takes over ones default key bindings, for those that don't use them it should not be an issue but for those that do it is an annoyance to be considered.
For sudo !!
, this can also be achieved by making this custom function:
function sudo
if test "$argv" = !!
eval command sudo $history[1]
else
command sudo $argv
end
end

Con Very slow
Much of the functionality in Fish was not written with performance in mind. However, scripting in a shell is not supposed to be about performance. If you need it, use a full-blown programming environment to get it. Shells are for gluing the high-performance tools together.
Alternative Products
