How to get last argument of previous command in Fish

While working at the Bash shell prompt, you can access the very last argument of the preceding command using $_.

For example:

$ vim foobar.txt
$ vim $_

To get the effect of $_ in Fish, press Alt+Up. Fish will insert the last argument of the previous command for you right there at the shell prompt.

If you find this command is not working, please check if your terminal multiplexer (tmux or Byobu) or your GUI terminal or windowing environment has not already assigned that key for something else.


Environment variables in Fish

Environment variables can be set just like any other variable in the Fish shell.

  • To export an environment variable to the shell, add it in ~/.config/fish/
set -x FOO_ENV_VAR /home/joe/bin/some_foo_dir
  • If this a environment variable with many values, then set it as an array. In Fish, you set an array variable with a space-delimited series of values:
set -x FOO_ENV_VAR /home/joe/bin/some_foo_dir /usr/local/foo_dir

Under Bash, you might have set this same environment variable in ~/.bashrc as:

export FOO_ENV_VAR=/home/joe/bin/some_foo_dir:/usr/local/foo_dir
  • If the environment variable with many values already exists and you want to prepend or append a value to it, the technique is the same. For example, to prepend to PATH:
set -x PATH /home/joe/bin/some_foo_dir $PATH
  • Three special environment variables: PATH, CDPATH and MANPATH are treated differently by Fish. These arrive from the environment to Fish as colon-separated, they are converted to array so we can set them easily as shown above using space-delimiter and then they are sent back to the environment as colon-separated. This logic can be seen in the Fish source code file src/env.cpp here. This is also explained in this issue.

  • The problem now is that there are many other environment variables which need to be colon-delimited, but Fish does not do that. For example, the dynamic linker that is used to load up DLLs when a binary executes requires LD_LIBRARY_PATH environment variable to be colon-delimited. I got errors when this variable was set using space-delimiters: cannot open shared object file: No such file or directory

  • If you run into any problems with an environment variable that takes a series of values, then check back to see how it is set in traditional shells like Bash. If it is colon-delimited there, then you might need to make it colon-delimited in Fish too. But, do remember to enclose it in double quotes for variable expansion to work correctly. For example:

set -x FOO_ENV_VAR "/home/joe/bin/some_foo_dir:$FOO_ENV_VAR"

Tried with: Fish 2.2 and Ubuntu 14.04

Time command in Fish shell

Running the time command in the Bash shell, gives output split across the very familiar real, user and sys sections:

$ time ./do_something

real    0m1.210s
user    0m0.158s
sys 0m0.033s

However, running time in the Fish shell, gives output in a different format:

$ time ./do_something

0.38user 0.08system 0:07.34elapsed 6%CPU (0avgtext+0avgdata 20116maxresident)k
7968inputs+192outputs (89major+25318minor)pagefaults 0swaps

The difference in output is because these two time programs are different. The Bash time is a command internal to that shell. Fish does not have in inbuilt time command, so it runs the binary /usr/bin/time whose output is of the above format.

If you like the simple format of the Bash time command and want it under Fish, use the -p option of the time binary:

$ time -p ./do_something

real 1.81
user 0.17
sys 0.02

If you would like this to be the default output format of time in Fish, then add the below lines to your ~/.config/fish/ file:

function time --description="Time just like in Bash"
    command time --portability $argv

Tried with: Time 1.7-24, Fish 2.1.1, Bash 4.3.11 and Ubuntu 14.04

How to change directory in shell using Ranger

One of the uses of Ranger can be to conveniently change to a directory in the shell that launched Ranger. To do this, we use the --choosedir option of Ranger. Pass this the name of a file and when Ranger is closed it will write the directory it was in to that file. You can then read the contents of this file in your shell to change to that location.

For Bash, a function that can do this is provided in in the Ranger source code.

For Fish, I have written a similar function that you can add to your ~/.config/fish/

To use Ranger like this, invoke it at the shell as ranger-cd. When you quit Ranger, fish will change its current directory to that in Ranger.

Tried with: Ranger 1.6.1, Fish 2.0.0 and Ubuntu 14.04

How to update a bash shell with new bashrc file

If you have made some changes to your bashrc file, how do you update your current bash shell without exiting it?

One solution is to ask bash to read and execute your bashrc file, thus updating itself from the changed commands and settings in it. This can be done using the source built-in command of bash.

For example, to update my current shell with my changed .bashrc:

$ source ~/.bashrc

Tried with: bash 4.2.24 and Ubuntu 12.04.1 LTS