|
NAMEfish-faq - fish-shell faqWHAT IS THE EQUIVALENT TO THIS THING FROM BASH (OR OTHER SHELLS)?See Fish for bash usersHOW DO I SET OR CLEAR AN ENVIRONMENT VARIABLE?Use the set command:set -x key value # typically set -gx key value set -e key 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: key=value echo $key begin; set -lx key value; echo $key; end Note that "exported" is not a scope, but an additional bit of state. A variable can be global and exported or local and exported or even universal and exported. Typically it makes sense to make an exported variable global. HOW DO I CHECK WHETHER A VARIABLE IS DEFINED?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?A global variable of the same name already exists.Environment variables such as EDITOR or TZ can be set universally using set -Ux. However, if there is an environment variable already set before fish starts (such as by login scripts or system administrators), it is imported into fish as a global variable. The variable scopes are searched from the "inside out", which means that local variables are checked first, followed by global variables, and finally universal variables. This means that the global value takes precedence over the universal value. To avoid this problem, consider changing the setting which fish inherits. If this is not possible, add a statement to your configuration file (usually ~/.config/fish/config.fish): set -gx EDITOR vim HOW DO I RUN A COMMAND EVERY LOGIN? WHAT'S FISH'S EQUIVALENT TO .BASHRC OR .PROFILE?Edit the file ~/.config/fish/config.fish [1], creating it if it does not exist (Note the leading period).
HOW DO I SET MY PROMPT?The prompt is the output of the fish_prompt function. Put it in ~/.config/fish/functions/fish_prompt.fish. For example, a simple prompt is:function fish_prompt set_color $fish_color_cwd echo -n (prompt_pwd) set_color normal echo -n ' > ' end You can also use the Web configuration tool, fish_config, to preview and choose from a gallery of sample prompts. If you want to modify your existing prompt, you can use funced and funcsave like: >_ funced fish_prompt # This opens up your editor (set in $EDITOR). # Modify the function, # save the file and repeat to your liking. # Once you are happy with it: >_ funcsave fish_prompt This also applies to fish_right_prompt and fish_mode_prompt. WHY DOES MY PROMPT SHOW A [I]?That's the fish_mode_prompt. It is displayed by default when you've activated vi mode using fish_vi_key_bindings.If you haven't activated vi mode on purpose, you might have installed a third-party theme that does it. If you want to change or disable this display, modify the fish_mode_prompt function, for instance via funced. HOW DO I CUSTOMIZE MY SYNTAX HIGHLIGHTING COLORS?Use the web configuration tool, fish_config, or alter the fish_color family of environment variables.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?Quick answer:Run the following command in fish: function fish_title; end; funcsave fish_title Problem solved! The long answer: 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. HOW DO I RUN A COMMAND FROM HISTORY?Type some part of the command, and then hit the ↑ (up) or ↓ (down) arrow keys to navigate through history matches. Additional default key bindings include Control+P (up) and Control+N (down). See Searchable command history for more information.WHY DOESN'T HISTORY SUBSTITUTION ("!$" ETC.) WORK?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 Alt+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:
See documentation for more details about line editing in fish. HOW DO I RUN A SUBCOMMAND? THE BACKTICK DOESN'T WORK!fish uses parentheses for subcommands. For example:for i in (ls) echo $i end MY COMMAND (PKG-CONFIG) GIVES ITS OUTPUT AS A SINGLE LONG STRING?Unlike other shells, fish splits command substitutions only on newlines, not spaces or tabs or the characters in $IFS.That means if you run echo x(printf '%s ' a b c)x It will print xa b c x, because the "a b c " is used in one piece. But if you do echo x(printf '%s\n' a b c)x it will print xax xbx xcx. In the overwhelming majority of cases, splitting on spaces is unwanted, so this is an improvement. However sometimes, especially with pkg-config and related tools, splitting on spaces is needed. In these cases use string split -n " " like: g++ example_01.cpp (pkg-config --cflags --libs gtk+-2.0 | string split -n " ") The -n is so empty elements are removed like POSIX shells would do. HOW DO I GET THE EXIT STATUS OF A COMMAND?Use the $status variable. This replaces the $? variable used in some other shells.somecommand if test $status -eq 7 echo "That's my lucky number!" end If you are just interested in success or failure, you can run the command directly as the if-condition: if somecommand echo "Command succeeded" else echo "Command failed" end Or if you just want to do one command in case the first succeeded or failed, use and or or: somecommand or someothercommand See the documentation for test and if for more information. MY COMMAND PRINTS NO MATCHES FOR WILDCARD BUT WORKS IN BASHIn short: quote or escape the wildcard:scp user@ip:/dir/"string-*" When fish sees an unquoted *, it performs wildcard expansion. 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 scp user@ip:/dir/string-* or 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 for f in ./*.mpg; do # We need to test if the file really exists because # the wildcard might have failed to match. test -f "$f" || continue mympgviewer "$f" done (from http://mywiki.wooledge.org/BashFAQ/004) For these reasons, fish does not do this, and instead expects asterisks to be quoted or escaped if they aren't supposed to be expanded. This is similar to bash's "failglob" option. I ACCIDENTALLY ENTERED A DIRECTORY PATH AND FISH CHANGED DIRECTORY. WHAT HAPPENED?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 asking for more help.WHY WON'T SSH/SCP/RSYNC CONNECT PROPERLY WHEN FISH IS MY LOGIN SHELL?This problem may show up as messages like "Received message too long", "open terminal failed: not a terminal", "Bad packet length", or "Connection refused" with strange output in ssh_exchange_identification messages in the debug log.This usually happens because fish reads the user configuration file (~/.config/fish/config.fish) always, whether it's in an interactive or login or non-interactive or non-login shell. This simplifies matters, but it also means when config.fish generates output, it will do that even in non-interactive shells like the one ssh/scp/rsync start when they connect. Anything in config.fish that produces output should be guarded with status is-interactive (or status is-login if you prefer): if status is-interactive ... end The same applies for example when you start tmux in config.fish without guards, which will cause a message like sessions should be nested with care, unset $TMUX to force. I'M GETTING WEIRD GRAPHICAL GLITCHES (A STAIRCASE EFFECT, GHOST CHARACTERS, CURSOR IN THE WRONG POSITION,...)?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:
This also means that a few things are unsupportable:
HOW DO I MAKE FISH MY DEFAULT SHELL?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. UNINSTALLING FISHIf you want to uninstall fish, first make sure fish is not set as your shell. Run chsh -s /bin/bash if you are not sure.If you installed it with a package manager, just use that package manager's uninstall function. If you built fish yourself, assuming you installed it to /usr/local, do this: rm -Rf /usr/local/etc/fish /usr/local/share/fish ~/.config/fish rm /usr/local/share/man/man1/fish*.1 cd /usr/local/bin rm -f fish fish_indent WHERE CAN I FIND EXTRA TOOLS FOR FISH?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:
This is not an exhaustive list and the fish project has no opinion regarding the merits of the repositories listed above or the scripts found therein. AUTHORfish-shell developersCOPYRIGHT2021, fish-shell developers
Visit the GSP FreeBSD Man Page Interface. |