Skip to content

fish shell Notes

chris edited this page Aug 10, 2022 · 51 revisions

Contents

General Usage πŸ”

To print key codes sent to the terminal using sed

sed -n l

Then press a key combination to see what is sent to the terminal, ie. alt ←

^[b^[[1;3D

Presently, Sep 23, 2018, fish does not support loading with no configuration, or disabling configuration files or directories. To get a status of when this might be possible see this

To build fish shell from git source on macOS using GNU autotools

cd $HOME/Library/Caches/Homebrew/fish--git \
git pull origin master \
autoreconf --no-recursive
make
make install

use either reinstall or upgrade, but not both

Working a pseudo brace expansion in fish, using index range expansion

Contrast to BASH fish shell does not play well with using brace expansion when working with ranges. That said, fish provides index range expasion which works well as a substitue to BASH's brace expansion. πŸ‘

To perform an action in BASH on a range of values

rm -rf /path/to/mr-fancy-dir-{1..42}

To perform the above expression in fish, ie. remove a range of directories or values

rm -rif (ls /path/to/mr-fancy-dir)[1..42]

The above expression should get the same mileage as bash. πŸš—

An alternative 🎸🀘 way to perform a task on a range of values is to use the seq command provided by BSD or GNU

wget http://chrisrjones.com/attachments/(seq 3 10)

Scripting πŸ”

Working with for loops

To iterate over all the files in a directory and make a change to all files, ie. change all files ending in .jpg to .jpeg

for i in *.jpg; mv -iv $i (basename $i .jpg).jpeg; end

The above command will change all .jpg files to .jpgeg in the current working directory.

Iterating files with fish

To prepend a sequential numerical value to a directory of files based on their creation date using fish shell.

fish does not evaluate expressions the same way bash or other POSIX shells do.

  1. To list all the files in a directory from oldest to newest, ie. oldest at the top of the list, and newest at the bottom of the list.
ls -tr

The above command will list just the basename for the files in a directory and put the oldest file at the top of the outputted list, and new file at the bottom of the list. The -r flag reverses the order. πŸ‘

To iterate over files in a directory a while loop can be used.

set n 0
ls -tr | while read fname
  set n (math $n + 1)
  mv -iv $fname (printf '%02d%s\n' $n $fname)
end

The above command will iterate over the entire list of files in the directory and increment the variable n for each file, and the printf command will prepend a two digit number to the file name starting with 01 and should sequential number each file based on it's creation date.

Putting the below line at the top of a script file will exit the script if there are any errors.

set -e

☣️ Highly opinionated statement below

Fish follows a philsophy of avoding special syntax for things that can be expressed as a command, ie. the difference in BASH and fish handle process substitution.

To record a terminal session that doesn't record time between key presses or commands but rather records, ie waits for input, but doesn't record the time between input, thus allowing for terse terminal session recordings. πŸ‘ there is the script command.

macOS uses the BSD derivative of script

To record a terminal session using script on macOS

script -r /path/to/mr-fancy-script-recording.log

To playback the script recording using script

script -p /path/to/mr-fancy-script-recording.log

To debug and direct all output from a command run via a fish shell

fish -d 3 /path/to/mr_buggy.fish > /path/to/all/output ^&1

More detailed info on redirection with the fish shell see

To create four new files using brace expansion

touch {macOS,windows,linux,freebsd}

To display the know tab completions for a command within fish shell.

fish_update_completions

The above command, fish_update_completions requires Python >= 3.x fish_update_completions should be run periodically ie. with a cron job to stay current with completions.

then to display a list of completions for a command, ie.

<command> -
Screenshot πŸ“Έ πŸ’³ fish-shell-command-completions

the tab key must be pressed after inserting the - to display a list of completions.

To prevent fish from stair stepping emojis when using a prompt that has the right prompt enabled

Screenshot πŸ“Έ fish-shell-stairway-to-hell
set -gx fish_emoji_width 2

To reload the fish shell environment without closing the current shell session, ie. closing a tab / window in iTerm2.

The below command is useful when editing files such as config.fish and want to see the changes applied in the current session.

exec fish

To see if the current shell / terminal combination can support italics

echo -e "\e[3m foo \e[23m"

The above command should print foo

Working with find

To remove the executable bits from files with various extensions

find . \( -iname '*.png' -o -iname '*.jpg' \) -exec chmod 644 '{}' \;

Searching For Patterns the_platinum_searcher

To search for a pattern within all text / source code files within the current working directory

pt [mr-fancy-expression-to-search-for]

The above command is quite useful for finding syntax errors that are scattered through a directory structure, and the specific file / line is not specified within standard error output.

Going back down the character encoding πŸ‡πŸ•³

How to display a number to a power, ie. 2 to the 2^2 power?

Numbers represented as exponents on a computer screen are referred to as superscript.

Character Encoding Useful Links

Character Encoding macOS

To input a specific Unicode character by its four digit sequence using the Emoji & Symbols contextual menu in macOS

  1. Bring up the Emoji & Symbols macOS native contextual menu, and to input a-superscript 2 input u+00b2 into the menu, and a superscript Β² should become selectable within the context menu.

Working with jobs

recently i ran brew install qt@5 -v -s and the job took ~ 24hrs to run on the mojave virtual machine, and using control+z to suspend the job was not working and and i did not start the task within a tmux or screen session. what to do? fortunately i was able to use the kill command to stop the process and then later resume the process from a different ssh session. πŸ‘ thanks to this stackoverflow q/a.

Moving a job / process from foreground and running it in the background

  1. If a job is running the foreground of an interactive shell, thus not allowing the user to interact with the shell, the process can be suspended with control+z
  2. Then the process can be moved to the background with bg command.

The above bg command will unsuspend the process and resume its operation.

  1. To keep the process running after the interactive shell session has been exited from, run disown

If the process is running the background and needs to be moved to the foreground of an interactive shell session use the fg command.

Working with the PATH environment variable

To display a list of entries contained in the PATH environment variable

pretty-path

The above command is dependent on the pretty-path fish function being setup in the fish shell environment

To manually prepend a directory to the $PATH

set PATH /path/to/fancy/dir/of/bin $PATH

To erase a path from the outputted list

set -e PATH[<the_number_of_the_path_entry_to_delete>]

Example

set -e PATH[3]

Credit πŸ’³

An alternative way to remove a path entry from $PATH

set PATH (string match -v /some/path/entry $PATH)

Custom PATH workflow

If modifying PATH entries in stored in 001_load_paths.fish then a couple of steps will be required to update all interactive fish shell instances.

  1. Remove unecessary PATH entries from 001_load_paths.fish
  2. Remove paths from fish using the path_remove fish function

path_remove only needs to be invoked once in a single interactive fish shell.

  1. If running a bunch of different interactive fish shell instances within tmux, save the configuration, then detach from tmux, and kill the detached session.
  2. Start a new tmux session, restore tmux from saved session, all interactive fish shells have the updated path entries.

πŸ”

Working with aliases

To print a list of aliases for the current fish session

alias

To remove an alias πŸ’³

functions -e <name_of_alias>

Example,

functions -e less

Random hacky shit

Created the below alias on both nix and macOS to allow tmux to find fish stored in a centeral location.

ln -sf (which fish) /bin/fish

Working with Functions πŸ”

To print the description for a custom function

functions --details -v <name_of_custom_function>

Example

╭─capin at rogue in /opt/Code/dotfiles (master βœ”)
╰─λ functions --details -v toggle_homebrew_python_path                                121 < 14:18:21
/Users/capin/.config/fish/functions/toggle_homebrew_python_path.fish
autoloaded
1
scope-shadowing
toggle homebrew python 🐍

Working with abbreviations

⚠️ With recent version of fish abbreviations are stored as universal variables, that said all universal variables can be edited by modifying ~/config/fish/fish_universal_variables file, as opposed to removing manually using abbr -e [mr-fancy-abbr].

Frameworks

To list installed packages / themes

omf list

To update a package or theme, ie. neolambda

omf update neolambda

To update the oh-my-fish framework itself

omf update omf

OMF oh-my-fish stores the contents of a plugin / package in

$HOME/.local/share/omf/pkg

OMF Creating Packages

A guide for creating a theme / plugin for omf can be found here

  • fzf is command line fuzzy finder that be used from the CLI or from within a text editor such as vim to quickly find files, a la spotlight search.

fzf is written in go and is asynchronous out of the box.

To search through the command history control + r

To search from files from within the current directory control + t

🚨 The below is a hacky solution to get fzf working with different brew prefixes

To get the brew prefix

echo (brew --prefix)
  • Create the below directory structure with a symlink on *nix to mimic that of macOS
/usr/local/opt/fzf/shell/key-bindings.fish
  • Then symlink /usr/local/opt/fzf/shell/key-bindings.fish to ~/.config/fish/functions/key-bindings.fish

Profiling

Unlike other shells fish does not have a builtin time command, so rely on using the systems time command; usually located at /usr/bin/time

To get a ballpark figure of how long a program takes to process on a nix system

/usr/bin/time make

on macOS

To print / profile how long it takes to launch an interactive fish shell

/usr/bin/time -l fish -ic exit

As of April 10, 2018 fish v2.7.1 with my current dotfiles is taking ~ 0.88 seconds to launch an interactive shell session. πŸ™„ As of December 6, 2018, an interactive fish shell launches in ~ 0.73 seconds or 730 milliseconds

Fish also has a builtin command flag of -p or --profile that writes profiling information to PROFILE_FILE environment variable.

A useful command for profiling fish

fish --profile /tmp/fish.prof -c 'true'; sort -nk1 /tmp/fish.prof | tail -n 20

A more verbose profiling solution for measure launch time of fish

fish -p /path/to/mr-fancy-profile.txt -c exit

The unit of measurement in mr-fancy-profile.txt are microseconds.

BASH Notes mostly unsorted

Question Does BASH support datatypes the way other languages such as python or javascript have float int object array ..etc, etc.

Answer In short, BASH does not support traddtional data types that the above mentioned languages support, however it does support some basic data types such as int and String, and that's about it, see this for more information.

When developing a bash script sometimes it may be useful to call a single function from a script, and run just that function from the script and NOT run any other function from the script. There is a sort of way this can be done, by using source to load the shell/BASH script within the current interactive bash session, and then a function can be called from that script

echo "example"
source `~/.local/bin/script.sh
singleFunction

A non interactive way to debug a BASH script

#!/bin/bash -x

Place the above line at the top of the bash script

To syntax check a BASH script

bash -n /path/to/bash/script.sh

To test / print / log the entire BASH login process

env -i bash --login -xv

BASH Working with environment variables

To unset an environment variable in BASH

unset [env-var]

Ex

unset HOST_CC

To list all exported variables and functions

export -p

aliases should be placed within $HOME/.bashrc or $HOME/.bash_aliases.

Make sure bash sources the .bash_aliases file if it is used.

To add an alias for BASH place the custom shell alias within the ~/.bashrc file.

To add a custom PATH to the BASH environment, ie. /mr/fancy/pants/path/ add it to $HOME/.bashrc ie.

PATH=/mr/fancy/pants/path:$PATH

To lint, ie. check a bash script for syntax errors

bash -n mr-fancy-bash-script.sh

To use a no-op instruction with BASH

if [ `id -un` = capin ] ; then
  echo "yup its me"
elif [ `id -un` = root ] ; then
  : # `:` is the no-op instruction
else # everyone else
  echo "erbody else"
fi

To test a file / directory is writeable use [ -w within a shell script.

To change all files in a directory with an sh extension to have an executable user bit.

find /path/to/dif -name "*.sh" -execdir chmod u+x {} +

Advanced BASH Usage πŸ™„

When working with a BASH script and the return keyword is used within a function and the criteria / condition is meet and the return keyword is executed the BASH script will exit of of the current function regardless if more lines within the function could have been executed.

To pad a directory of files with 000 etc, so listing the files, will print the files in a more sane order, useful for viewing files in "correct" order.

  1. pad all existing files with a set of zeros
for f in mr-fancy-file[0-9]*; do mv $f `printf mr-fancy-file%05d ${f#mr-fancy-file}`; done

OPTIONAL if desired reapply extension to modified files

  1. reapply extension
for f in *; do mv "$f" "f.mr-fancy-file-extension"; done

another alternative way to rename a directory of files with incrementing numbers
ie. file name with spaces.mp4 to 001.file name with spaces.mp4 is see below link

https://askubuntu.com/a/1095649/134740 requires installing the perl script rename ie. brew install rename

bass

If bass is installed using a fish plugin manager, simple BASH scripts be run from within fish, ie.

bash export X=3

will properly set the env var using fish grammar. πŸ‘

Executing a programs through BASH as a fish shell function, use

bash -c '$HOME/path/to/mr-fancy-program "$@"' dummy $argv

see

Useful Links πŸ”— in no particular order

Troubleshooting

Fish provides a bind builtin / command to work with key bindings when using an interactive fish shell session.

To paste text on the CLI using fish use control + v and text stored in the system clipoard should be pasted at the prompt.

To list all the different modes fish provides when working with key bindings

bind -L

should output something like

default
paste

TODOs

  • better organize the notes about using bass with fish shell, ie. don't put them in with BASH Notes
Clone this wiki locally