Recs.
Updated
friendly interactive shell = fish
fish is a smart and user-friendly command line
shell for macOS, Linux, and the rest of the family.
Specs
Pros
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 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 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
Cons
Con Not POSIX compliant
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