Command history in Fish

Fish maintains a history of all commands you have executed.

  • To list the history in reverse chronological order:
$ history
  • To list the history along with the time at which each command was executed:
$ history --show-time

Note that this is a very useful feature to check when a particular command was executed. However, this feature was only added in Fish 2.4.0 and is not available in older versions.

  • To search for a substring foo in history:
$ history foo
  • To merge the history of all open sessions of Fish right now:
$ history --merge

Fish does this merge only when it is exited. This is because Fish does not want to update the common history file at the end of every command. This might be for performance and to avoid race conditions.

However, sometimes you execute a long command in one Fish session and might want to repeat that in another session. This is a quick way to merge all histories, so that that command is now available in history of the second session for easy autocompletion.

Tried with: Fish 2.4.0 and Ubuntu 14.04

fish_pwd error

Problem

I updated the Fish shell using the apt command:

$ sudo apt install fish

After the update, Fish threw up this error:

fish: __fish_pwd
      ^
in command substitution
    called on standard input


in command substitution
    called on standard input

Solution

This turned out to be because the /usr/share/fish/functions/__fish_pwd.fish function file it was looking for could not be found! The apt update had screwed up and had deleted some essential configuration files of Fish.

I removed and reinstalled Fish shell:

$ sudo apt purge fish
$ sudo apt install fish

I noticed that the above function file was correctly installed and available now. Fish worked fine after this 🙂

Tried with: Fish 2.4.0 and Ubuntu 14.04

How to read in silent mode in Fish

Silent mode is an useful feature in shells to read sensitive information like passwords. The text typed by the user is not displayed on the displayed nor stored anywhere on file.

Sadly, the Fish shell does not have a true silent mode in its read command. Also, when used with default options, the password (or input) entered to the read command is stored in ~/.config/fish/fish_read_history.

The best we can do is to make the read command not store its history. This can be achieved by passing /dev/null as the history file for read:

read -m /dev/null var_to_store_password

Tried with: Fish 2.2.0 and Ubuntu 14.04

How to update environment variable of existing Tmux session

Problem

I use Byobu (which is a wrapper on Tmux) to maintain shell sessions on the many servers I login to. I connect, disconnect and reconnect to the same Tmux sessions on these servers. When I reconnect back to an existing Tmux session, a new value is assigned to the DISPLAY environment variable. If I create a new Tmux session, by opening a new split or tab, then Tmux sets the new DISPLAY value correctly for that session. However, existing Tmux sessions have their old DISPLAY value which gives the familiar cannot open display error. I can find out the new DISPLAY value and set it manually in the existing session, but that is cumbersome.

Solution

I found a simple solution to this problem. Whenever I SSH to a server, I save the new DISPLAY assigned to this server in a .display.txt file in the home directory. For example, this can be done in .bashrc:

echo $DISPLAY > ~/.display.txt

To pick up the new DISPLAY value from this file in existing sessions, create a shell alias or function that you can call when you realize that the environment variable is wrong.

For example, for Fish shell, I added a ~/.config/fish/functions/set_display.fish file with these lines:

function set_display
    set --export DISPLAY (cat ~/.display.txt)
end

When I need to update DISPLAY, I just call set_display at the shell! 🙂

Tried with: Byobu 5.74, Tmux 1.8 and Fish 2.2.0

How to get autocomplete for command options in Fish

Fish has support to autocomplete the options of any command at the shell. (This is sometimes called tab completions.) For example, when I type ls - and TAB, Fish shows me the options available for the ls command. This works even when you’ve typed out part of an option. Fish generates this information by parsing all the man pages installed on your system.

If you find that Fish autocomplete is not working for the options of a command, that can be fixed easily by asking Fish to reindex from man pages. The Fish function that you need to run for this is: fish_update_completions.

I recently installed Git. Since Git is infamous for its myriad command-line options I missed having autocomplete at the shell for Git command options. After running fish_update_completions, I could get autocomplete for options of all Git commands! The icing on top was to discover that Fish could autocomplete options even for my Git aliases!

Tried with: Fish 2.2.0

Missing argument to exec

Problem

I run a find command at the Fish shell and get this error:

$ find . -type f -exec sed -i 's/foo/bar/g' {} +
find: missing argument to `-exec`

Solution

This command has nothing wrong with it, it works under Bash. Fish expands the curly braces by default. So, for this to work, just enclose the curly braces in single quotes, so that it is not expanded. More details here.

Tried with: Fish 2.2.0 and Ubuntu 14.04

How to redirect and pipe in Fish

  • Redirection of stdin and stdout works just like in Bash:
$ ./a.out > out.txt
$ ./a.out < in.txt
  • Stdout can be piped just like in Bash:
$ ./a.out | less
  • Stderr can be redirected as:
$ ./a.out ^ out.txt
  • Stderr can be piped as:
$ ./a.out ^| less
  • To redirect both stdout and stderr:
$ ./a.out 2>&1 out.txt
  • To pipe both stdout and stderr:
$ ./a.out 2>&1 | less

Tried with: Fish 2.0.0 and Ubuntu 14.04

How to check for SSH session in shell

There are times when you want to check if you are in a SSH session from your shell. For example, I like to change the shell prompt based on whether it is in a local machine or in a SSH session on another machine.

An easy way to do this is to check if any environment variable related to SSH has been set. For example, I check if the SSH_CLIENT variable is set in my shell. In Fish, this can be done by checking the result of set --query SSH_CLIENT for example.

How to set default shell for Byobu

I like to have Fish as my default shell in Byobu. I add these lines to my ~/.byobu/.tmux.conf:

set -g default-shell   /usr/bin/fish
set -g default-command /usr/bin/fish

Note that Byobu will set the SHELL environment variable to the above path. That is, even if you want to set SHELL to something else in your shell’s init file, that will be overridden by Byobu.

Tried with: Byobu 5.74 and Ubuntu 14.04

How to deactivate a virtualenv

After a virtualenv has been activated and used, you might want to get back your normal shell environment.

No matter whether you are using Bash or Fish, the activation script adds a deactivate function. Use this to deactivate the virtualenv:

$ deactivate

Tried with: Fish 2.2.0 and Ubuntu 14.04