Bash tricks
From wikinotes
Parallelization with Xargs
# 8x parallel processes at once echo "${git_repos[@]}" \ | tr ' ' '\n' \ | xargs -P 8 -I REPO git pull REPO
Skip first N lines of output
cat << EOF | tail -n +2 # prints all lines, starting with #2 (fiona) NAME fiona alex katie EOF
Strip Leading/Trailing Whitespace
echo ' abc def hij ' | awk '{$1=$1;print}'
raw output
Sometimes when parsing shell output, it is useful to see the actual raw output before colours/escape sequences are applied in order to diagnose issues. In this instance, you can pipe a command to
cat
.( ls -l ; ls -l --color=always ) | cat -vet total 41624$ drwxr-xr-x 2 will will 4096 Dec 2 08:01 new$ -rw-r--r-- 1 will will 42557440 Dec 2 08:01 old.tar$ total 41624$ drwxr-xr-x 2 will will 4096 Dec 2 08:01 ^[[01;34mnew^[[0m$ -rw-r--r-- 1 will will 42557440 Dec 2 08:01 old.tar$
Find the Number of tokens in a line:
VAR='some/string/with words' echo $VAR | tr -cd "/" | wc -c
Repeat character N times
printf -- '=%.0s' {1..5} # repeat '=' 5 times printf -- '=%.0s' $(seq 1 5) # repeat '=' 5 timesSome useful applications
# print '-'s across the full width of terminal printf "%$(tput cols)s" | tr ' ' '-' # print '='s matching length of '$header' header="hello my friend" echo "$header" printf "=%.0s" $(seq 1 ${#header}); echo
Iterate over tokenize string
Useful for iterating over
$PATH
style variable paths that may contain spaces.echo "$PATH" | tr ':' '\n' | while read -r path; do echo "--$path" done
calculate sum of input-lines
# returns sum (15) cat << EOF | awk "{ sum += \$1 } END { if (NR > 0) print sum }" 1 2 3 4 5 EOF
calculate average of input-lines
# returns avg (3) cat << EOF | awk "{ sum += \$1 } END { if (NR > 0) print sum / NR }" 1 2 3 4 5 EOF
calculate p95 percentile of input-lines
n=4 divides data into 1/4s.
we're choosing the 2nd index (3rd quartile or 75th percentile).# 95th percentile cat << EOF | python -c 'import sys; import numpy; q = list(map(lambda x: float(x), filter(lambda x: x.strip() != "", sys.stdin.read().split("\n")))); print(numpy.quantile(q, 0.95))' 1 2 3 4 EOF
UUIDs
- linux: e2fsprogs, libuuid
- freebsd: base
uuidgen # generate a uuid
Simple Menu
Consider using ncurses or dialog instead before implementing your own menu.
The following should also work.# Format: ${MENU_ITEM} ${COMMAND} ... CHOICES=( "say hi" "echo hi && sleep 1" "say bye" "echo bye && sleep 1" ) print_error() { # """ prints an error with a sleep # """ message="$1" echo echo echo $message sleep 2 } show_menu() { # """ prints menu w/ choices # """ clear echo "Choose Desktop:" for ((i=1; i<=${#CHOICES[@]}; i+=2)); do local index="$(expr $i / 2)" local name="${CHOICES[$i]}" echo " ${index}) ${name}" done } choose_menu_index() { # """ requests an integer with the menu choice you'd like to load # """ local num_choices="$(expr $(expr ${#CHOICES[@]} / 2) - 1)" echo echo -n "Press (0-${num_choices} [default:0]): " && read index # defaults to 0 test -z "$index" && index=0 # must be integer if ! [ "$index" -eq "$index" ] 2> /dev/null ; then print_error "Expected Integer. Received: ${index}" return 1 fi # reject numbers above $num_choices if test "$index" -gt "$num_choices" ; then print_error "Expected Integer <${num_choices}. Received: ${index}" return 1 fi # exec chosen menu, after newline local array_index=$((2*$(expr $index + 1))) eval "${CHOICES[$array_index]}" } mainloop() { if [[ $(tty) == /dev/tty1 ]] ; then while true; do show_menu choose_menu_index done fi }
Executable Archive
...or rather, an executable with an embedded archive that can be unzipped.