fish
fish is a smart and user-friendly command line shell for Linux, macOS, and the rest of the family.
Usage
Abbreviations
To avoid needless typing, a frequently-run command like git checkout can be abbreviated to gco using the abbr command.
abbr -a gco git checkout
After entering gco and pressing space or enter, a gco in command position will turn into git checkout in the command line. If you want to use a literal gco sometimes, use ctrl-space.
Abbreviations are a lot more powerful than just replacing literal strings. For example you can make going up a number of directories easier with this:
function multicd
echo cd (string repeat -n (math (string length -- $argv[1]) - 1) ../)
end
abbr --add dotdot --regex '^\.\.+$' --function multicdNow, .. transforms to cd ../, while ... turns into cd ../../ and .... expands to cd ../../../.
The advantage over aliases is that you can see the actual command before using it, add to it or change it, and the actual command will be stored in history.
Custom bindings
In addition to the standard bindings listed here, you can also define your own with bind:
# Just clear the commandline on control-c
bind ctrl-c 'commandline -r ""'
Put bind statements into config.fish or a function called fish_user_key_bindings.
If you change your mind on a binding and want to go back to fish’s default, you can simply erase it again:
bind --erase ctrl-c
History
After a command has been executed, it is remembered in the history list. Any duplicate history items are automatically removed. By pressing the up and down keys, you can search forwards and backwards in the history. If the current command line is not empty when starting a history search, only the commands containing the string entered into the command line are shown.
By pressing alt-up (↑) and alt-down (↓), a history search is also performed, but instead of searching for a complete commandline, each commandline is broken into separate elements just like it would be before execution, and the history is searched for an element matching that under the cursor.
For more complicated searches, you can press ctrl-r to open a pager that allows you to search the history. It shows a limited number of entries in one page, press ctrl-r again to move to the next page and ctrl-s to move to the previous page. You can change the text to refine your search.
History searches are case-insensitive unless the search string contains an uppercase character. You can stop a search to edit your search string by pressing escape or pagedown.
Prefixing the commandline with a space will prevent the entire line from being stored in the history. It will still be available for recall until the next command is executed, but will not be stored on disk. This is to allow you to fix misspellings and such.
The command history is stored in the file ~/.local/share/fish/fish_history (or $XDG_DATA_HOME/fish/fish_history if that variable is set) by default. However, you can set the fish_history environment variable to change the name of the history session (resulting in a <session>_history file); both before starting the shell and while the shell is running.
See the history command for other manipulations.
Private mode
Fish has a private mode, in which command history will not be written to the history file on disk. To enable it, either set $fish_private_mode to a non-empty value, or launch with fish --private (or fish -P for short).
If you launch fish with -P, it both hides old history and prevents writing history to disk. This is useful to avoid leaking personal information (e.g. for screencasts) or when dealing with sensitive information.
You can query the variable fish_private_mode (if test -n "$fish_private_mode" ...) if you would like to respect the user’s wish for privacy and alter the behavior of your own fish scripts.
Directory History
Navigating directories is usually done with the cd command, but fish offers some advanced features as well.
The current working directory can be displayed with the pwd command, or the $PWD special variable. Usually your prompt already does this.
Fish automatically keeps a trail of the recent visited directories with cd by storing this history in the dirprev and dirnext variables.
Several commands are provided to interact with this directory history:
dirhprints the historycdhdisplays a prompt to quickly navigate the historyprevdmoves backward through the history. It is bound toalt-left(←)nextdmoves forward through the history. It is bound toalt-right(→)
Configuration
To store configuration write it to a file called ~/.config/fish/config.fish.
.fish scripts in ~/.config/fish/conf.d/ are also automatically executed before config.fish.
These files are read on the startup of every shell, whether interactive and/or if they’re login shells. Use status --is-interactive and status --is-login to do things only in interactive/login shells, respectively.
Shell Scripting
Shebang
Because shell scripts are written in many different languages, they need to carry information about which interpreter should be used to execute them. For this, they are expected to have a first line, the shebang line, which names the interpreter executable.
A script written in bash would need a first line like this:
#!/bin/bash
When the shell tells the kernel to execute the file, it will use the interpreter /bin/bash.
For a script written in another language, just replace /bin/bash with the interpreter for that language. For example: /usr/bin/python for a python script, or /usr/local/bin/fish for a fish script, if that is where you have them installed.
If you want to share your script with others, you might want to use env to allow for the interpreter to be installed in other locations. For example:
#!/usr/bin/env fish
echo Hello from fish $version
This will call env, which then goes through PATH to find a program called “fish”. This makes it work, whether fish is installed in (for example) /usr/local/bin/fish, /usr/bin/fish, or ~/.local/bin/fish, as long as that directory is in PATH.
The shebang line is only used when scripts are executed without specifying the interpreter. For functions inside fish or when executing a script with fish /path/to/script, a shebang is not required (but it doesn’t hurt!).
When executing files without an interpreter, fish, like other shells, tries your system shell, typically /bin/sh. This is needed because some scripts are shipped without a shebang line.
Variables
In Fish, variables are assigned using the set command:
set name "Alice"
set -g global_var "I'm global"
set -x PATH $PATH /custom/bin # export variable to child processes-g: Sets a global variable.-x: Exports the variable.- Arrays are space-separated:
set colors red green blue
echo $colors[1] # Outputs: redConditionals
Fish uses if, else if, and else:
set age 20
if test $age -ge 18
echo "You're an adult"
else if test $age -ge 13
echo "You're a teenager"
else
echo "You're a child"
endSwitch Statements
Use switch for cleaner branching with string values:
set lang "rust"
switch $lang
case rust
echo "You're using Rust!"
case python
echo "Python is cool too."
case '*'
echo "Unknown language"
endLoops
for Loop
for color in red green blue
echo $color
endwhile Loop
set count 1
while test $count -le 3
echo "Count: $count"
set count (math $count + 1)
endFunctions
Define reusable blocks of code with function:
function greet
echo "Hello, $argv"
end
greet "World" # Output: Hello, World$argvholds all passed arguments.$argv[1]is the first argument.
Returning Values
Functions can return more than just a status code. They can return actual output:
function get_username
echo "alice"
end
set user (get_username)
echo $user # Outputs: aliceFor status codes, use return:
function is_even
if test (math "$argv[1] % 2") -eq 0
return 0
else
return 1
end
endEvents
Fish supports event-driven scripting using functions --on-event:
function notify_start --on-event fish_prompt
echo "Shell is ready!"
endEvents can be fired with the emit command, and do not have to be defined before. The names just need to match. For example:
function handler --on-event imdone
echo generator is done $argv
end
function generator
sleep 1
# The "imdone" is the name of the event
# the rest is the arguments to pass to the handler
emit imdone with $argv
endTools
Builtins to do a task, like
cdto change the current directory.echoorprintfto produce output.set_colorto colorize output.setto set, query or erase variables.readto read input.stringfor string manipulation.pathfor filtering paths and handling their components.mathdoes arithmetic.argparseto make arguments easier to handle.countto count arguments.typeto find out what sort of thing (command, builtin or function) fish would call, or if it exists at all.testchecks conditions like if a file exists or a string is empty.containsto see if a list contains an entry.evalandsourceto run fish code from a string or file.statusto get shell information, like whether it’s interactive or a login shell, or which file it is currently running.abbrmanages Abbreviations.bindto change bindings.completemanages completions.commandlineto get or change the commandline contents.fish_configto easily change fish’s configuration, like the prompt or colorscheme.randomto generate random numbers or pick from a list.