Since fish 3.1 you can set an environment variable for just one command using the ``key=value some command`` syntax, like in other shells. The two lines below behave identically - unlike other shells, fish will output ``value`` both times::
Use ``set -q var``. For example, ``if set -q var; echo variable defined; end``. To check multiple variables you can combine with ``and`` and ``or`` like so::
if set -q var1; or set -q var2
echo either variable defined
end
Keep in mind that a defined variabled could also be empty, either by having no elements (if set like ``set var``) or only empty elements (if set like ``set var ""``). Read on for how to deal with those.
How do I check whether a variable is not empty?
-----------------------------------------------
Use ``string length -q -- $var``. For example, ``if string length -q -- $var; echo not empty; end``. Note that ``string length`` will interpret a list of multiple variables as a disjunction (meaning any/or)::
if string length -q -- $var1 $var2 $var3
echo at least one of these variables is not empty
end
Alternatively, use ``test -n "$var"``, but remember that **the variable must be double-quoted**. For example, ``if test -n "$var"; echo not empty; end``. The ``test`` command provides its own and (-a) and or (-o)::
if test -n "$var1" -o -n "$var2" -o -n "$var3"
echo at least one of these variables is not empty
end
If you want to know if a variable has *no elements*, use ``set -q var[1]``.
Why doesn't ``set -Ux`` (exported universal variables) seem to work?
Use the web configuration tool, :ref:`fish_config <cmd-fish_config>`, or alter the :ref:`fish_color family of environment variables <variables-color>`.
How do I change the greeting message?
-------------------------------------
Change the value of the variable ``fish_greeting`` or create a ``fish_greeting`` function. For example, to remove the greeting use::
set -U fish_greeting
Or if you prefer not to use a universal variable, use::
set -g fish_greeting
in config.fish.
I'm seeing weird output before each prompt when using screen. What's wrong?
Fish is trying to set the titlebar message of your terminal. While screen itself supports this feature, your terminal does not. Unfortunately, when the underlying terminal doesn't support setting the titlebar, screen simply passes through the escape codes and text to the underlying terminal instead of ignoring them. It is impossible to detect and resolve this problem from inside fish since fish has no way of knowing what the underlying terminal type is. For now, the only way to fix this is to unset the titlebar message, as suggested above.
Note that fish has a default titlebar message, which will be used if the fish_title function is undefined. So simply unsetting the fish_title function will not work.
Type some part of the command, and then hit the :kbd:`↑` (up) or :kbd:`↓` (down) arrow keys to navigate through history matches. Additional default key bindings include :kbd:`Control`\ +\ :kbd:`P` (up) and :kbd:`Control`\ +\ :kbd:`N` (down).
Because history substitution is an awkward interface that was invented before interactive line editing was even possible. Instead of adding this pseudo-syntax, fish opts for nice history searching and recall features. Switching requires a small change of habits: if you want to modify an old line/word, first recall it, then edit.
As a special case, most of the time history substitution is used as ``sudo !!``. In that case just press :kbd:`Alt`\ +\ :kbd:`S`, and it will recall your last commandline with `sudo` prefixed (or toggle a `sudo` prefix on the current commandline if there is anything).
In general, fish's history recall works like this:
- Like other shells, the Up arrow, :kbd:`↑` recalls whole lines, starting from the last executed line. A single press replaces "!!", later presses replace "!-3" and the like.
- If the line you want is far back in the history, type any part of the line and then press Up one or more times. This will filter the recalled lines to ones that include this text, and you will get to the line you want much faster. This replaces "!vi", "!?bar.c" and the like.
-:kbd:`Alt`\ +\ :kbd:`↑` recalls individual arguments, starting from the last argument in the last executed line. A single press replaces "!$", later presses replace "!!:4" and such. As an alternate key binding, :kbd:`Alt`\ +\ :kbd:`.` can be used.
- If the argument you want is far back in history (e.g. 2 lines back - that's a lot of words!), type any part of it and then press :kbd:`Alt`\ +\ :kbd:`↑`. This will show only arguments containing that part and you will get what you want much faster. Try it out, this is very convenient!
- If you want to reuse several arguments from the same line ("!!:3*" and the like), consider recalling the whole line and removing what you don't need (:kbd:`Alt`\ +\ :kbd:`D` and :kbd:`Alt`\ +\ :kbd:`Backspace` are your friends).
See :ref:`documentation <editor>` for more details about line editing in fish.
In short: :ref:`quote <quotes>` or :ref:`escape <escapes>` the wildcard::
scp user@ip:/dir/"string-*"
When fish sees an unquoted ``*``, it performs :ref:`wildcard expansion <expand-wildcard>`. That means it tries to match filenames to the given string.
If the wildcard doesn't match any files, fish prints an error instead of running the command::
> echo *this*does*not*exist
fish: No matches for wildcard '*this*does*not*exist'. See `help expand`.
echo *this*does*not*exist 2>| xsel --clipboard
^
Now, bash also tries to match files in this case, but when it doesn't find a match, it passes along the literal wildcard string instead.
That means that commands like the above
..code-block:: sh
scp user@ip:/dir/string-*
or
..code-block:: sh
apt install postgres-*
appear to work, because most of the time the string doesn't match and so it passes along the `string-*`, which is then interpreted by the receiving program.
But it also means that these commands can stop working at any moment once a matching file is encountered (because it has been created or the command is executed in a different working directory), and to deal with that bash needs workarounds like
If fish is unable to locate a command with a given name, and it starts with ``.``, ``/`` or ``~``, fish will test if a directory of that name exists. If it does, it is implicitly assumed that you want to change working directory. For example, the fastest way to switch to your home directory is to simply press ``~`` and enter.
How can I use ``-`` as a shortcut for ``cd -``?
-----------------------------------------------
In fish versions prior to 2.5.0 it was possible to create a function named ``-`` that would do ``cd -``. Changes in the 2.5.0 release included several bug fixes that enforce the rule that a bare hyphen is not a valid function (or variable) name. However, you can achieve the same effect via an abbreviation::
abbr -a -- - 'cd -'
The open command doesn't work.
------------------------------
The ``open`` command uses the MIME type database and the ``.desktop`` files used by Gnome and KDE to identify filetypes and default actions. If at least one of these environments is installed, but the open command is not working, this probably means that the relevant files are installed in a non-standard location. Consider :ref:`asking for more help <more-help>`.
In a terminal, the application running inside it and the terminal itself need to agree on the width of characters in order to handle cursor movement.
This is more important to fish than other shells because features like syntax highlighting and autosuggestions are implemented by moving the cursor.
Sometimes, there is disagreement on the width. There are numerous causes and fixes for this:
- It is possible the character is simply too new for your system to know - in this case you need to refrain from using it.
- Fish or your terminal might not know about the character or handle it wrong - in this case fish or your terminal needs to be fixed, or you need to update to a fixed version.
- The character has an "ambiguous" width and fish thinks that means a width of X while your terminal thinks it's Y. In this case you either need to change your terminal's configuration or set $fish_ambiguous_width to the correct value.
- The character is an emoji and the host system only supports Unicode 8, while you are running the terminal on a system that uses Unicode >= 9. In this case set $fish_emoji_width to 2.
This also means that a few things are unsupportable:
- Non-monospace fonts - there is *no way* for fish to figure out what width a specific character has as it has no influence on the terminal's font rendering.
- Different widths for multiple ambiguous width characters - there is no way for fish to know which width you assign to each character.
If you installed fish manually (e.g. by compiling it, not by using a package manager), you first need to add fish to the list of shells by executing the following command (assuming you installed fish in /usr/local)::
echo /usr/local/bin/fish | sudo tee -a /etc/shells
If you installed a prepackaged version of fish, the package manager should have already done this for you.
In order to change your default shell, type::
chsh -s /usr/local/bin/fish
You may need to adjust the above path to e.g. ``/usr/bin/fish``. Use the command ``which fish`` if you are unsure of where fish is installed.
Unfortunately, there is no way to make the changes take effect at once. You will need to log out and back in again.
The fish user community extends fish in unique and useful ways via scripts that aren't always appropriate for bundling with the fish package. Typically because they solve a niche problem unlikely to appeal to a broad audience. You can find those extensions, including prompts, themes and useful functions, in various third-party repositories. These include: