Skip to content

Instantly share code, notes, and snippets.

@kernkraft235
Created February 28, 2026 13:53
Show Gist options
  • Select an option

  • Save kernkraft235/27b0fd165e0329800441906b35a77ea7 to your computer and use it in GitHub Desktop.

Select an option

Save kernkraft235/27b0fd165e0329800441906b35a77ea7 to your computer and use it in GitHub Desktop.
Fish Shell Cheatsheat

fish shell cheatsheet (focused)


quoting

  • single quotes: no expansion at all
echo '$HOME *.txt'
  • double quotes: allow variable + command substitution only
echo "home is $HOME"
echo "pwd is $(pwd)"
  • no quotes: full expansion (globs, variables, braces, etc.)

  • variables:

set foo 1 2 3
echo $foo      # → 1 2 3 (multiple args)
echo "$foo"    # → "1 2 3" (single arg)

escaping

  • general: \ escapes next char
echo \$HOME
echo \*
echo \(
  • common sequences:
\n   newline
\t   tab
\r   carriage return
\xHH hex byte
\uXXXX unicode
\UXXXXXXXX unicode (32-bit)
  • literal space:
echo hello\ world
  • continuation (special case):
echo foo \
bar

expansions (order matters)

order:

  1. command substitution
  2. variable expansion
  3. brace expansion
  4. wildcard expansion

variable

echo $HOME

brace

echo file.{c,h}

wildcard

ls *.txt
ls **.log
  • unmatched glob → command fails (not passed literally)

combining

set a x y
echo pre$a        # → prex prey
echo {$a}post     # → xpost ypost

command substitution

  • syntax:
echo (pwd)
echo $(pwd)
  • behavior:

    • splits on newline into multiple args
echo (printf "a\nb\n")   # → a b
  • prevent splitting:
echo "$(pwd)"
  • common pattern:
set files (ls *.txt)
  • process substitution (fish-specific):
diff (cmd1 | psub) (cmd2 | psub)

continuations

  • backslash newline:
echo foo \
bar
  • no whitespace inserted

redirection

basic FDs

  • stdin: 0
  • stdout: 1
  • stderr: 2

output

echo hi > out.txt        # overwrite
echo hi >> out.txt       # append

stderr

cmd 2> err.txt
cmd 2>> err.txt

stdin

cmd < input.txt
cmd <? input.txt         # fallback to /dev/null

combine stdout + stderr

cmd &> all.txt           # overwrite both
cmd &>> all.txt          # append both

equivalent:

cmd > all.txt 2>&1

redirect to FD

cmd > &2                 # stdout → stderr
cmd 2> &1                # stderr → stdout

close FD

cmd 2>&-                 # close stderr

noclobber

cmd >? file.txt          # fail if exists
cmd 2>? err.txt

pipes

cmd1 | cmd2
cmd 2>| less             # pipe stderr
cmd &| less              # pipe stdout+stderr

evaluation order (important)

  • pipe is created first
  • then redirections left → right

example:

cmd 2>&1 | less

quick examples

# safe variable usage
set f "my file.txt"
rm "$f"

# list files or nothing (no glob failure)
set files *.txt
count $files >/dev/null; and ls $files

# redirect everything
make &> build.log

# silence stdout, keep stderr
cmd > /dev/null

# silence both
cmd > /dev/null 2>&1

# stderr only through pager
make 2>| less

# inline variable override
PATH=/tmp/bin $PATH/mycmd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment