This page documents bash tips and snippets that I typically use in my shell scripts. I keep them together to be able to quickly check them if required.
In your .bashrc file:
export BLACK="\[\e[00;30m\]" export BLUE="\[\e[00;34m\]" export GREEN="\[\e[00;32m\]" export CYAN="\[\e[00;36m\]" export RED="\[\e[00;31m\]" export PURPLE="\[\e[00;35m\]" export BROWN="\[\e[00;33m\]" export GRAY="\[\e[01;30m\]" export L_GRAY="\[\e[00;37m\]" export L_BLUE="\[\e[01;34m\]" export L_GREEN="\[\e[01;32m\]" export L_CYAN="\[\e[01;36m\]" export L_RED="\[\e[01;31m\]" export L_PURPLE="\[\e[01;35m\]" export L_YELLOW="\[\e[01;33m\]" export L_WHITE="\[\e[01;37m\]" export NORMAL="\[\e[00m\]" # Red prompt for root export PS1="${L_RED}\u@\H:${BLUE} \w #${NORMAL} " # For a normal user, use this instead: #export PS1="${L_YELLOW}\u@\H:${BLUE} \w \$${NORMAL} "
# SH if [ "${HOST:0:4}" = "user" ]; then ...; fi # BASH if [[ "$HOST" =~ ^user.* ]]; then ... ; fi # BASH (without quotes, for * to expand): if [[ $HOST == user* ]]; then ... ; fi
LASTARG="${@: -1}"
set -- "${@:1:$(($#-1))}"
This code allows to use colours in your scripts, and disable them giving –nocolor
# Terminal colours RED="\e[31m" YELLOW="\e[33m" NORMAL="\e[0m" GREEN="\e[92m" # Disable terminal colours if "--nocolor" flag is passed as last argument: LASTARG="${@: -1}" if [ "${LASTARG}" == "--nocolor" ]; then RED="" YELLOW="" NORMAL="" GREEN="" fi # Now you can safely write colors with: echo -e "* File $FILE ${YELLOW}already patched${NORMAL} ${GREEN}[success]${NORMAL}\n"
Sometimes our scripts accept paths as command line arguments. As we don't know if the user will add a trailing bar to the path (/tmp or /tmp/), we can use bash's % operator to remove it:
# Remove trailing / from $1 (if it ends with a /). DESTDIR="${1%/}" # Another example: BACKUPDIR="${BACKUPDIR%/}"
unset MYPWD prompt="Please insert the password: " while IFS= read -p "$prompt" -r -s -n 1 char do if [[ $char == $'\0' ]] then break fi prompt='*' MYPWD+="$char" done echo
We should always remove temporary files created with mktemp. But if our script it's killed with CTRL+C or with kill, the temporary file won't be deleted. Bash provides a signal trapping mechanism to allow us to minimize this effect:
TEMPFILE=$(mktemp) trap "rm -f ${TEMPFILE}; exit 1" INT TERM (your code...) rm -f $TEMPFILE trap - INT TERM
Note that there is a small race condition between the tempfile creation and the trap command (the file is created and the trap is not yet set).
By setting "set -o vi
" in our .bashrc file (or typing it directly in the terminal), we change from "emacs-mode" to "vi-mode" (check set -o
). While in Vi mode, we can use the Vi keyboard commands to work in the terminal. Each command starts in insert mode but we can go to command mode by pressing ESC.
In your .bashrc:
export VISUAL=/usr/bin/vim export EDITOR=/usr/bin/vim set -o vi
Now, in command mode, the following Vi keys/commands will act as expected:
Specially useful commands are included:
Searches also work like in vi:
Unfortunately, with the vi mode I lost the only "emacs" command that I typically used: ESC + . (to recover the last argument from the previous command). To solve this, we have a couple of alternatives:
First: you can use bash's !$ or $_ but it is not expanded until you execute the command and it's quite dangerous used that way.
Second: you can use Alt+. instead (which also works in emacs mode) by adding the following to your ~/.inputrc
file:
set editing-mode vi set keymap vi-insert $if mode=vi "\e.":yank-last-arg $endif
Then, edit your ~/.bashrc
and after the set -o vi
add:
if [[ $- =~ i ]] && [[ -f ~/.inputrc ]]; then bind -f ~/.inputrc fi
If you don't mind losing Vi's dot (.) functionality, you can also add the following to your .inputrc
file:
set keymap vi-command $if mode=vi ".":insert-last-argument $endif
Finally, another option would be to switch to command mode and press _
(underscore): ESC + _
.
If you also want to "block" the arrow keys in command mode, add the following in your .inputrc
file:
set keymap vi-command $if mode=vi "\eOD":"" "\e[D":"" "\eOC":"" "\e[C":"" "\eOA":"" "\e[A":"" "\eOB":"" "\e[B":"" $endif
If we are used also to other emacs shortcuts like "Clear the Screen" (Ctrl+L) or "Home" / "End" (Ctrl+A and Ctrl+E) we can add them to our .inputrc file:
set editing-mode vi set keymap vi-insert $if mode=vi (...) "\C-l":clear-screen "\C-a":beginning-of-line "\C-e":end-of-line "\C-w":backward-kill-word $endif set keymap vi-command $if mode=vi (...) "\C-l":clear-screen "\C-a":beginning-of-line "\C-e":end-of-line "\C-w":backward-kill-word $endif