Fish

Fish is a smart and user-friendly command line shell for Linux, macOS, and the rest of the family.

See the official tutorial and documentation.

Why fish?
Fish is a fully-equipped command line shell (like bash or zsh) that is smart and user-friendly. Fish supports powerful features like syntax highlighting, autosuggestions, and tab completions that just work, with nothing to learn or configure.

If you want to make your command line more productive, more useful, and more fun, without learning a bunch of arcane syntax and configuration options, then fish might be just what you're looking for!

Getting started
Once installed, just type in  into your current shell to try it out!

You will be greeted by the standard fish prompt, which means you are all set up and can start using fish:

&gt; fish Welcome to fish, the friendly interactive shell Type help for instructions on how to use fish you@hostname ~&gt; This prompt that you see above is the fish default prompt: it shows your username, hostname, and working directory. - to change this prompt see  - to switch to fish permanently see.

From now on, we'll pretend your prompt is just a  to save space.

Learning fish
This tutorial assumes a basic understanding of command line shells and Unix commands, and that you have a working copy of fish.

If you have a strong understanding of other shells, and want to know what fish does differently, search for the magic phrase unlike other shells, which is used to call out important differences.

Or, if you want a quick overview over the differences to other shells like Bash, see.

For the full, detailed description of how to use fish interactively, see.

For a comprehensive description of fish's scripting language, see.

Running Commands
Fish runs commands like other shells: you type a command, followed by its arguments. Spaces are separators:

&gt; echo hello world hello world This runs the command  with the arguments   and. In this case that's the same as one argument, but in many cases it's not. If you need to pass an argument that includes a space, you can  with a backslash, or   it using single or double quotes:

&gt; mkdir My\ Files &gt; cp ~/Some\ File 'My Files' &gt; ls &quot;My Files&quot; Some File
 * 1) Makes a directory called &quot;My Files&quot;, with a space in the name
 * 1) Copies a file called &quot;Some File&quot; in the home directory to &quot;My Files&quot;

Getting Help
Run  to open fish's help in a web browser, and   with the page (like  ) to open it in a man page. You can also ask for help with a specific command, for example,  to open in a web browser, or   to see it in the terminal.

&gt; man set set - handle shell variables Synopsis...

Syntax Highlighting
You'll quickly notice that fish performs syntax highlighting as you type. Invalid commands are colored red by default:

&gt; /bin/mkd

A command may be invalid because it does not exist, or refers to a file that you cannot execute. When the command becomes valid, it is shown in a different color:

&gt; /bin/mkdir Valid file paths are underlined as you type them:

&gt; cat ~/somefi

This tells you that there exists a file that starts with, which is useful feedback as you type.

These colors, and many more, can be changed by running, or by modifying   directly.

For example, if you want to disable (almost) all coloring:

fish_config theme choose none This picks the &quot;none&quot; theme. To see all themes:

fish_config theme show Just running  will open up a browser interface that allows you to pick from the available themes.

Wildcards
Fish supports the familiar wildcard. To list all JPEG files:

&gt; ls *.jpg lena.jpg meena.jpg santa maria.jpg You can include multiple wildcards:

&gt; ls l*.p* lena.png lesson.pdf Especially powerful is the recursive wildcard ** which searches directories recursively:

&gt; ls /var/**.log /var/log/system.log /var/run/sntp.log If that directory traversal is taking a long time, you can +  out of it.

For more, see.

Pipes and Redirections
You can pipe between commands with the usual vertical bar:

&gt; echo hello world | wc     1       2      12 stdin and stdout can be redirected via the familiar  and. stderr is redirected with a.

&gt; grep fish &lt; /etc/shells &gt; ~/output.txt 2&gt; ~/errors.txt To redirect stdout and stderr into one file, you need to first redirect stdout, and then stderr into stdout:

&gt; make &gt; make_output.txt 2&gt;&amp;1 For more, see  and.

Autosuggestions
As you type fish will suggest commands to the right of the cursor, in gray. For example:

&gt; /bin/h ostname

It knows about paths and options:

&gt; grep --i gnore-case

And history too. Type a command once, and you can re-summon it by just typing a few letters:

&gt; r sync -avze ssh. myname@somelonghost.com:/some/long/path/doo/dee/doo/dee/doo

To accept the autosuggestion, hit  (right arrow) or  +. To accept a single word of the autosuggestion, +  (right arrow). If the autosuggestion is not what you want, just ignore it.

If you don't like autosuggestions, you can disable them by setting  to 0:

set -g fish_autosuggestion_enabled 0

Tab Completions
A rich set of tab completions work &quot;out of the box&quot;.

Press  and fish will attempt to complete the command, argument, or path:

&gt; /pri =&gt; /private/

If there's more than one possibility, it will list them:

&gt; ~/stuff/s ~/stuff/script.sh (Executable, 4.8kB) ~/stuff/sources/ (Directory)

Hit tab again to cycle through the possibilities.

fish can also complete many commands, like git branches:

&gt; git merge pr =&gt; git merge prompt_designer &gt; git checkout b  builtin_list_io_merge (Branch) builtin_set_color (Branch) busted_events (Tag)

Try hitting tab and see what fish can do!

Variables
Like other shells, a dollar sign followed by a variable name is replaced with the value of that variable:

&gt; echo My home directory is $HOME My home directory is /home/tutorial This is known as variable substitution, and it also happens in double quotes, but not single quotes:

&gt; echo &quot;My current directory is $PWD&quot; My current directory is /home/tutorial &gt; echo 'My current directory is $PWD' My current directory is $PWD Unlike other shells, fish has no dedicated  syntax for setting variables. Instead it has an ordinary command:, which takes a variable name, and then its value.

<pre class="fish-docs-samples">&gt; set name 'Mister Noodle' &gt; echo $name Mister Noodle (Notice the quotes: without them,  and   would have been separate arguments, and   would have been made into a list of two elements.)

Unlike other shells, variables are not further split after substitution:

<pre class="fish-docs-samples">&gt; mkdir $name &gt; ls Mister Noodle In bash, this would have created two directories &quot;Mister&quot; and &quot;Noodle&quot;. In fish, it created only one: the variable had the value &quot;Mister Noodle&quot;, so that is the argument that was passed to, spaces and all.

You can erase (or &quot;delete&quot;) a variable with  or

<pre class="fish-docs-samples">&gt; set -e MyVariable &gt; env | grep MyVariable (no output) For more, see.

Exports (Shell Variables)
Sometimes you need to have a variable available to an external command, often as a setting. For example many programs like  or   read the   variable to figure out your preferred pager (the program that lets you scroll text). Other variables used like this include,   (to configure your language) and. You'll note these are written in ALLCAPS, but that's just a convention.

To give a variable to an external command, it needs to be &quot;exported&quot;. Unlike other shells, fish does not have an export command. Instead, a variable is exported via an option to, either   or just.

<pre class="fish-docs-samples">&gt; set -x MyVariable SomeValue &gt; env | grep MyVariable MyVariable=SomeValue It can also be unexported with  or.

This works the other way around as well! If fish is started by something else, it inherits that parents exported variables. So if your terminal emulator starts fish, and it exports  set to , fish will receive that setting. And whatever started your terminal emulator also gave it some variables that it will then pass on unless it specifically decides not to. This is how fish usually receives the values for things like,   and  , without you having to specify them again.

Exported variables can be local or global or universal - &quot;exported&quot; is not a ! Usually you'd make them global via.

For more, see.

Lists
The  command above used quotes to ensure that   was one argument. If it had been two arguments, then  would have been a list of length 2. In fact, all variables in fish are really lists, that can contain any number of values, or none at all.

Some variables, like, only have one value. By convention, we talk about that variable's value, but we really mean its first (and only) value.

Other variables, like, really do have multiple values. During variable expansion, the variable expands to become multiple arguments:

<pre class="fish-docs-samples">&gt; echo $PATH /usr/bin /bin /usr/sbin /sbin /usr/local/bin Variables whose name ends in &quot;PATH&quot; are automatically split on colons to become lists. They are joined using colons when exported to subcommands. This is for compatibility with other tools, which expect $PATH to use colons. You can also explicitly add this quirk to a variable with, or remove it with.

Lists cannot contain other lists: there is no recursion. A variable is a list of strings, full stop.

Get the length of a list with :

<pre class="fish-docs-samples">&gt; count $PATH 5 You can append (or prepend) to a list by setting the list to itself, with some additional arguments. Here we append /usr/local/bin to $PATH:

<pre class="fish-docs-samples">&gt; set PATH $PATH /usr/local/bin You can access individual elements with square brackets. Indexing starts at 1 from the beginning, and -1 from the end:

<pre class="fish-docs-samples">&gt; echo $PATH /usr/bin /bin /usr/sbin /sbin /usr/local/bin &gt; echo $PATH[1] /usr/bin &gt; echo $PATH[-1] /usr/local/bin You can also access ranges of elements, known as &quot;slices&quot;:

<pre class="fish-docs-samples">&gt; echo $PATH[1..2] /usr/bin /bin &gt; echo $PATH[-1..2] /usr/local/bin /sbin /usr/sbin /bin You can iterate over a list (or a slice) with a for loop:

<pre class="fish-docs-samples">for val in $PATH echo &quot;entry: $val&quot; end Lists adjacent to other lists or strings are expanded as  unless quoted (see  ):
 * 1) Will print:
 * 2) entry: /usr/bin/
 * 3) entry: /bin
 * 4) entry: /usr/sbin
 * 5) entry: /sbin
 * 6) entry: /usr/local/bin

<pre class="fish-docs-samples">&gt; set a 1 2 3 &gt; set 1 a b c &gt; echo $a$1 1a 2a 3a 1b 2b 3b 1c 2c 3c &gt; echo $a&quot; banana&quot; 1 banana 2 banana 3 banana &gt; echo &quot;$a banana&quot; 1 2 3 banana This is similar to.

For more, see.

Command Substitutions
Command substitutions use the output of one command as an argument to another. Unlike other shells, fish does not use backticks pkg-config string split $status $? set --query set --query PATH set --query arglbargl boogagoogoo $pipestatus &amp;&amp; || ! make ./configure sudo make install ./configure make $1 $argv functions seq PS1 funcsave fish_prompt ~/.config/fish/functions/fish_prompt.fish fish_config fish_config prompt $PATH $PATH $PATH $PATH config.fish .profile $fish_user_paths $PATH /usr/local/bin $PATH ~/.config/fish/config.fish config.fish ~/.config/fish/conf.d/ ~/.config/fish/functions/ ll ll.fish ~/.config/fish/functions set -U``:

<pre class="fish-docs-samples">&gt; set -U EDITOR vim Now in another shell:

<pre class="fish-docs-samples">&gt; echo $EDITOR vim

Ready for more?
If you want to learn more about fish, there is, the official gitter channel, an official mailing list, and the github page.