Skip to content

Instantly share code, notes, and snippets.

@tmichel
Created June 16, 2017 12:57
Show Gist options
  • Save tmichel/7c54ac272cbca70fea1fbe9c1e0a4321 to your computer and use it in GitHub Desktop.
Save tmichel/7c54ac272cbca70fea1fbe9c1e0a4321 to your computer and use it in GitHub Desktop.
Bash cheat sheet

Shell cheat sheet

Setting up iTerm

  • Use option as meta key:

Go to Preferences->Profiles tab. Select your profile on the left, and then open the Keyboard tab. At the bottom is a set of buttons that lets you select the behavior of the Option key. For most users, Esc+ will be the best choice.

  • Setting up word-by-word movement with Option+:

Go to Preferences->Keys tab. Add a new key mapping for Option+Left, from the Action dropdown pick Send Escape Sequence and put b in the textbox that appears. Repeat this for Option+Right but put f in the textbox.

Use bash 4.x

  • OSX default shell is bash 3.x
  • $ brew install bash

.bashrc vs .bash_profile

From the bash man page:

/bin/bash
      The bash executable
/etc/profile
      The systemwide initialization file, executed for login shells
~/.bash_profile
      The personal initialization file, executed for login shells
~/.bashrc
      The individual per-interactive-shell startup file
~/.bash_logout
      The individual login shell cleanup file, executed when a login shell exits
  • On OSX Terminal.app and iTerm opens a login shell by default
  • To unify .bashrc and .bash_profile
if [ -f ~/.bashrc ]; then
   source ~/.bashrc
fi

bash's hidden editor: readline

  • Offers line-editing and history capabilities
  • Basic key bindings are the same everywhere
  • Other platforms also use it. Try it it out in any OSX app.

Default key bindings

C: Control M: Meta (aka Alt or Options)

Movement:

  • C-a: Jump to start of line
  • C-e: Jump to end of line
  • C-f: Move forward one character
  • C-b: Move back one character
  • C-p or Up arrow: Previous command
  • C-n or Down arrow: Next command
  • M-f: Move forward one word
  • M-b: Move back one word

Editing:

  • M-d: Delete forward one word
  • C-d: Delete forward one character
  • C-h or Backspace: Delete backward one character
  • C-r: Reverse search through history
  • C-w: Delete current word until closest space
  • M-backspace: Delete current word until closest non-alphanumeric character
  • C-u: Delete (cut) to beginning of line
  • C-k: Delete (cut) to end of line
  • M-#: Comment out current line and show a new input line
  • C-t: Transpose two characters
  • M-t: Transpose two words.
  • M-u: Uppercase word at which the cursor is at the start
  • M-l: Lowercase word at which the cursor is at the start
  • M-c: Capitalize word at which the cursor is at the start
  • C-/: Undo
  • C-x C-x: Jump between two points in the current command
  • C-y: yank, paste from kill-ring
  • M-y: scroll through the kill-ring

History

  • history command

  • history | grep foo is super useful

  • !!: run previous command. Useful for sudo !!

  • !<num> run command

  • Useful settings:

      HISTCONTROL=ignoreboth
      HISTSIZE=10000
    
  • Use C-r to search your history

Escape codes

  • Chaning the terminal title: echo -e "\033];MY_NEW_TITLE\007"
  • Colors everywhere: echo -e "\e[31mHello World\e[0m"
  • Nice summary for colors in the terminal

Hidden and not so hidden bash features

  • $!: PID of previous command

  • $$: PID of current process

  • $?: exit status of previous command

  • !:1: first argument of the previous command

  • !:<n>: nth argument of the previous command

  • !!: last command and its arguments. Useful for sudo !!

  • C-x C-e: open the current command in $EDITOR and run when the editor was closed

  • aliases: one step away from automation

      alias ll='ls -AlF'
    
  • Run type <alias> to see what it is aliased to

Substitions and expansions

  • *: match 0 or more characters
  • [ab] or [a-z]: match character ranges
  • ?: match 0 or 1 character
  • {1..4}: generate numeric ranges, try echo {1..4}
  • echo foo.{bar,baz}: generate lists, output foo.bar foo.baz
  • running commands in subshells: `` and $()

Piping and redirection

  • Basics: cat foo | grep bar

  • Redirect and create a new file: echo foo > bar

  • Redirect and create append to file: echo foo >> bar

  • Redirect stdout/stderr: echo halp 1>&2

  • Using a command output as a file: <(ls)

      diff -y <(ls foo) <(ls bar)
    

Background jobs

  • Append & to the command to run in the background. E.g.: nc -l -k 8080 &
  • Send a foreground process to the background: C-z
  • List jobs: jobs
  • Bring job to the foreground: fg <job num>
  • Tip: use this with interactive programs such as vim to access the terminal.

Basic commands with a few tricks

A man file is usually there and they are usually well writter. Learn to read them! For bash builtin commands turn to man bash.

  • cat as a super basic editor, good for copy-pasting multiple lines into a file in the shell:

      cat > foo
      type stuff
      hit C-d to send an EOF character and close the file
    
  • less

    • Hit / to search
    • VIM keybindings kinda work for movement j/k/C-d/C-u
    • type -N or other options when less is running to turn on/off features
    • -N: show line numbers
    • -S: do not wrap lines
    • Shift-G: jump to end
    • gg: jump to start
    • Shift-F: tail file
    • -R: make sense of escape characters --> colors everywhere
  • cd - to jump back previous directory; uses $OLDPWD variable

  • cd without arguments jump to $HOME

  • finding files with find

      find . -name '[abc]*' # files starting with a or b or c
      find . -name foo -not -path './.git/*' # find foo but exclude the .git folder
      find . -maxdepth 1 # kinda like ls
      find . -name 'foo*' -type d # find directories starting with foo
    

    When you are using an * always wrap in in single-quotes because otherwise bash would exapnd it.

    Running a command for every match:

      find . -type f -exec sed -e 's/foo/bar/' {} \;
    

    Deleting matches

      find . -type f -name '*.log' -delete
    
  • cal: print calendar for the current month

  • cal 2017: print calendar for the year 2017

Searching for stuff

  • grep is built-in everywhere

  • grep on Linux and OSX is sligthly different

  • color output

      # Put this in your .bashrc
      alias grep='grep --color=auto'
    
  • extended regexp

      cat foo.log | grep -E '\w+=\w+' # search for key-value pairs separated by an equal sign
    
  • printing context around the matches

      cat foo.log | grep -C3 error # print previous and next 3 lines around matches
      cat foo.log | grep -A3 error # print 3 lines after matches
      cat foo.log | grep -B3 error # print 3 line before matches
    
  • search in a directory recursively

      grep -r foo src/
    
  • print only matching parts

      cat foo.log | grep -E '\w+=\w+' -o
    
  • search for lines not matching a pattern

      grep -r -v foo src/
    
  • count matches

      cat foo.log | grep bar -c
    
      # count all matches in a directory
      grep -c -h -r foo src/ | awk 'sum+=$0 {next} END { print sum }'
    
  • print only file names when content matches

      grep -r -l foo src/
    
  • print file names where there is not match

      grep -r -L foo src/
    
  • for better recursive searching use an alternative to grep: ag, ack, ripgrep

Basic text manipulation and display

Basic tools: tr, sed, awk, sort, uniq, cut, comm.

Transform strings with tr:

# Uppercase everything
$ head /usr/share/dict/words | tr '[:lower:]' '[:upper:]'

# Break into new lines
$ echo $PATH | tr ':' '\n'

# Replace numbers with x
$ echo a{1..100} | tr '[:digit:]' x

Search and replace with sed

sed on OSX differs from GNU sed. Install gnu-sed for more features.

$ brew install gnu-sed

Replace foo with bar in every file in a directory:

$ gsed -i -e 's/foo/bar/g' $(find . -type f)

Formatting tabular data:

$ cat > people.csv <<EOF
Name,Age,Job
Bob,54,Accountant
Rob,23,Stay at home dad
Al,98,Navy veteran
Kate,34,Product Manager
Lacy,22,Driver
EOF

# Formatted table
$ cat people.csv | column -t -s,

Displaying certain fields

$ cat people.csv | cut -d, -f1,3
$ cat people.csv | awk -F, '{ print $2 }'

Filtering with awk

# People over 50
$ cat people.csv | awk -F, '$2 > 50 { print $0 }'

Count occurences in a file

$ cat /usr/share/dict/words | cut -c -4 | tr '[:upper:]' '[:lower:]'  | sort | uniq -c

List short git SHA1 hashes

$ git rev-list HEAD | cut -c -7
@vbalazs
Copy link

vbalazs commented Jun 18, 2017

Nice collection of tricks, thanks!

What do you think about adding xargs to the list? Often works better than find -exec.

@tmichel
Copy link
Author

tmichel commented Jun 23, 2017

@vbalazs I don't even know why I leftxargs out. I'll add it. Thanks!

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