Command line tips
Fish shell
The Fish shell is a shell with very sane defaults that can do a lot out of the box and makes you feel at home right after installing it.
Beware though, some not-so-commonly-used features of bash do not exist in the fish shell and it isn’t compatible with POSIX sh
. Where it really shines is as an interactive shell.
The tutorial gives a quick and great overview of its capabilities.
Getting help
When in doubt
man cat
help cd
jq --help
,jq -h
apropos "list dir"
,man -k "list dir"
search the manual
Moving around
cd -
go to the last visited directorydirs
print the dirs stackpushd .
add current directory to the dirs stackpopd
pop and go to the last one
Working with files
> my-file
overwrites the file’s content>> my-file
appends to the file’s existing content< my-file
inputs the file’s content, same ascat my-file |
but without starting an additional processmkdir my-new-directory
make a new directorydiff <(ls) <(ls -a)
,<()
treats the output of the command as a file (doesn’t work in fish)
All the following commands support -v
for verbose and -i
for interactive
-
mv my-file new-file
moves a file -
cp my-file new-file
copies a file -
rm my-file
,rm -r my-directory
remove a file or directory -
file.conf{,.old}
will expand tofile.conf file.conf.old
cp file.conf{,.old}
create a backup filemv file.conf{.old,}
revert to the backupconvert file{.jpg,.png}
Combining CLI tools
Pipes !
seq 100 | grep 3 | wc -l
counts in how many numbers “3” appears between 1 and 100
Tee !
seq 100 | tee 100.txt
splits the output between stdout and the argument
Interacting with the clipboard
cat file.txt | xclip -selection clipboard
copy textxclip -selection clipboard -o > file.txt
paste text
Creating custom tools
Binary executable
Make them in a compiled language such as Rust, Go, C…
Interpreted scripts
Use the first line of the file to describe how to run it:
#!/usr/bin/env python3
def factorial(n):
res = 1
for i in range(2, n + 1):
res *= i
return res
if __name__ == "__main__":
import sys
n = int(sys.argv[1])
print(factorial(n))
./factorial.py 5
120
Shell functions
factorial() { echo 1; seq $1 | paste -s -d\* | bc; }
factorial 5
120
Can be put in config file to be reusable.
Aliases
alias la='ls -1a --group-directories-first'
Can be put in config file to be reusable.
Useful bits
wget -mkEpnp http://example.org
make an offline mirror of a site, short version of
--mirror --convert-links --adjust-extension --page-requisites --no-parent
while read in; do echo "$in"; done < file.txt
, repeat a command for every line of a file (doesn’t work in fish, but can be used withsh -c '...'
)tar -zcC /my/source/path my-folder > ~/my-backup-$(date +%s).tar.gz
make a quick backup
Juggle with the CLI
Modes
Most shells (fish, bash, zsh…) support two modes: the vi
mode and the emacs
mode with the mappings of each editor. Shells are in emacs
mode by default.
Vi bindings
Normal and insert mode, just like vim with nearly all of its bindings. The Vi mode is especially nice in the Fish shell.
fish_vi_key_bindings
fishset -o vi
bash & co
Emacs bindings
<C-/>
undo (doesn’t work in Fish)<C-a>
go to the beginning of the line<C-e>
go to the end of the line<C-k>
delete from cursor to the end of the command line<C-u>
delete from cursor to the beginning of the command line<C-r>
triggers history search<C-w>
delete from cursor to beginning of the word<C-y>
paste word or text that was cut using one of the deletion shortcuts (such as the one above) after the cursor<C-x-x>
move between start of command line and current cursor position (and back again)<Alt>b
move backward one word (or go to start of word the cursor is currently on)<Alt>f
move forward one word (or go to end of word the cursor is currently on)<Alt>d
delete to end of word starting at cursor (whole word if cursor is at the beginning of word)
Recall
- commands starting with a space don’t go in the history
<Alt>.
or<Esc>.
adds the last command’s last word<C-r>
search the history backwards<C-g>
escape from history searching mode<C-p>
previous command in history (i.e. walk back through the command history)<C-n>
next command in history (i.e. walk forward through the command history)
Control
<C-l>
clear the screen<C-s>
stops the output to the screen (for long running verbose command)<C-q>
allow output to the screen (if previously stopped using command above)<C-c>
terminate the command<C-z>
suspend/stop the command usebg
to run it in background,jobs
to list background jobs andfg
to bring them back&
after a command to run it in backgroundnohup
before a command to detach it’s life cyle from the current terminal&>/dev/null
redirects the output of the process to/dev/null
, use&>/dev/null/ &
after a command to ignore its output and run it in backgroundnohup command &>/dev/null &
hence creates a totally independent process,command </dev/null &>/dev/null &
achieves the same goal by instantly sending EOF to the program (using this you won’t see theDone
after the backgrounded process ends)
Bang ! (doesn’t work in fish)
!!
run last command,sudo !!
to add a forgotten sudo.!blah
run the most recent command that starts with “blah” (e.g. !ls)!blah:p
print out the command that !blah would run (also adds it as the latest command in the command history)!$
the last word of the previous command (same as Alt + .)!$:p
print out the word that !$ would substitute!*
the previous command except for the first word (e.g.find a b
givesa b
)!*:p
print out what !* would substitute
Substitutions (doesn’t work in fish')
^foo^bar
same as!!:s/foo/bar/
, replacefoo
withbar
in the last command and run it- Go up in history and hit
<C-o>
, this will execute the picked command and write the following one in the prompt