Skip to content

Instantly share code, notes, and snippets.

@rfong
Last active December 4, 2021 03:47
Show Gist options
  • Save rfong/6fd20a3a43a263217a9379ff305ccebf to your computer and use it in GitHub Desktop.
Save rfong/6fd20a3a43a263217a9379ff305ccebf to your computer and use it in GitHub Desktop.
fun bash things

no matter how long you've been using it, bash is an endless treasure trove of hidden gems thirsting to make your life better. here is a small tasting flight of favorite bash friends I've remembered to write down.

Navigation

My personal rule of thumb: if I've typed something more than twice, it's time to turn it into a macro.

When have you ever changed directories and not wanted to see the contents of your new location? Rarely.

# cd+ls, only the most used pair of commands of all time ever
function cl() {
  cd $@; ls;
}

Here, $@ redirects all of cl's parameters to cd.

On a related note, who wants to type three characters every time they have to go up another directory level? Let's simplify upward navigation:

alias .='cl ..'
alias ..='cl ../..'
alias ...='cl ../../..'
alias ....='cl ../../../..'
alias .....='cl ../../../../..'

Jump to your most recent prior location.

alias back='cl -'

Where am I?

Part of exploding your bash-mind is realizing that within this sandbox, you are blessed and cursed with ultimate power, and every character displayed in this terminal is an illusion built atop your personal sandbox of arbitrary inputs and outputs.

Changing your bash prompt to display user@host:directory. The first two are more useful if you spend a lot of time ssh'd into other machines.

export PS1='$(whoami)@$(hostname):$(pwd)$ '

Environment

sh script.sh and ./script.sh run the script within a subshell. If you have exports that you want to persist in your current shell, you need to use source.

Interactivity

Give user a y/n prompt.

read -r -p "Are You Sure? [y/n] " input
case "$input" in
  [yY])
    # do something
    ;;
  *)
    # do something else (or just exit)
    exit 1
    ;;
esac

Text manipulation

cut, sed, and awk, in decreasing order of simplicity and conversely increasing order of power, are the holy trifecta of slice-n-dice programs.

Select

Selecting every kth of N lines by modular arithmetic.

alias even="awk 'NR % 2 == 0'"
alias odd="awk 'NR % 2 == 1'"

Awkwardly, although arrays in bash are zero-indexed, this seems to be one-indexed, so you know what you're getting into.

$ for i in {1..10}; do echo $i; done | awk 'NR % 2 == 0'
2
4
6
8
10

Searching for something, and also seeing the lines before and after it.

grep -A1 -B1 ...

Chop and clean

squeeze consecutive whitespace & trim beginning

alias reduce="tr -s ' ' | sed -e 's/^[[:space:]]*//'"

extract first nonwhitespace field

alias firstarg="reduce | cut -d' ' -f1"

Cut off the first line:

tail -n +2

Cut off the last line:

sed \$d

Cut off the last field (as specified by cut's -d delimiter option) from a file. This reverses the line, cuts out the now-first field, then reverses the line back again.

cat file.txt | rev | cut -d' ' -f1 | rev

Transform

tr (short for “translate”) can be used to transform standard output with substitution or deletion of selected characters.

Transforming a string to uppercase:

> echo "HelLo wOrLd" | tr a-z A-Z
HELLO WORLD

Put all words in a string onto their own line:

> echo "One fish two fish" | tr -cs 'a-zA-Z0-9' '[\n*]'
One
fish
two
fish

One-line Caesar cipher:

> echo "Caesar Cipher" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
Pnrfne Pvcure

TODO

  • tac
  • !!
  • jq

Python from the command line, using the -m ("module") flag.

Make JSON readable

cat data.json | python -m json.tool

HTTP serve the current directory

# Start simple server on specified port or default to 8080
function py2serv() {
  python2 -m SimpleHTTPServer ${1:-8080}
}
function py3serv() {
  python3 -m http.server ${1:-8080}
}

I use this when locally developing on static web content that I don't otherwise need to run a server process for. Note that a SimpleHTTPServer isn't actually safe to use in production -- it's just really nice for testing.

When observing an HTML file via file://..., the browser will inevitably get confused or complain about Cross-Site Scripting attacks, or you won't always be able to use relative URLs. HTTP serving it makes testing a lot less painful.

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