#contents * BashShellOptions * BashArrays * BashPipeStatus * BashEnvironmentVariables * BashVariableSubstitution ## Useful keystrokes Pressing Esc followed by a key is equivalent to holding down Alt and pressing that key. We use `C-x` for Ctrl-x, `A-x` for Alt-x. ### Editing ```plaintext Ctrl+K # kill to end of line Ctrl+U # kill to start of line Ctrl+W # kill word before Ctrl+Y # paste last killed Ctrl+X+E # load current command into editor Requires VISUAL to be set to desired editor (def is emacs!??) Or EDITOR (VISUAL takes priority) Note that command is executed upon quit. Alt-F, Alt-B # forward/back one word Ctrl-R # search history ``` ### Command history ```plaintext Up # previous command in history Down # next command in history A-< # go to start of command history A-> # go to end of command history C-r # search history backwards C-s # search history forwards C-g # abort search Esc-p # prompt with : and go to previous command matching Esc-n # prompt with : and go to next command matching ``` #### Searching History Press `C-r` and start typing to search backwards; press Enter to execute the found command, or Esc to bring it up so that you can edit it. ### Kill Ring Pressing `C-k` 'kills' from the current character to the end of the line, and places the cut text into the 'kill ring'. ```plaintext C-k # kill to end of line C-u # kill to beginning of line Esc-backspace # kill previous word Esc-d # kill next word ``` Yanking ```plaintext C-y # Yank last killed text A-y # cycle through kill ring ``` ### Options Set with `shopt -s option` to set, and `shopt -u option` to unset it. ```plaintext histverify # when using !, allows editing command without immediately executing ``` ### Key Bindings Bind with e.g. ```plaintext bind '"C-t": "hello world"' # types 'hello world' when Ctrl-T pressed bind '"C-xd": kill-word' ``` #### Binding commands Commands like `kill-word` that you can bind to keystrokes. You can use ```plaintext bind -P # print out bindable commands and current key bindings ``` and ```plaintext bind -P | grep -v "not bound" | less ``` to see a list of current bindings (grep removes those commands not bound). #### Useful default bindings Completion: ```plaintext C-x/ # show possible file completions C-x@ # show possible host completions C-x~ # show possible uesrname completions C-x$ # show possible variable name completions C-x! # show possible command name completions A-= or A-? # show possible completions ``` ## Redirection ```plaintext ls > dirlist 2>&1 # stderr and stdout go into file ‘dirlist’ ls 2>&1 > dirlist # only stdout goes to file ‘dirlist’ ``` #### Special files ```plaintext /dev/stdout, /dev/stdin, /dev/stderr, /dev/fd/, /dev/tcp/host/port, /dev/udp/host/port E.g. Nc -l 3001 (on machine1), then Echo hello world > /dev/tcp/machine1/3001 ``` #### File Descriptors ```plaintext [n]>filename # redirect file descriptor n to filename [n]>|filename # as [n]>filename but overrides noclobber [n]>>filename # append instead of clobber [n]<&[m] # duplicate input file descriptor m to n [n]>&[m] # duplicate output file descriptor m to n [n]>&- # close file descriptor n ffmpeg 2>& filename # ERROR: ambiguous redirect ffmpeg >hello 2>&1 # redirects stdout, stderr to file hello [n]<&digit- # duplicate fd digit to n, then close fd [n]>&digit- # same but for output n<>filename # open filename for both reading and writing ``` #### Stdout and Stderr These are equivalent ```plaintext &>filename >&filename >filename 2>&1 ``` and all send both stdout and stderr to filename. These are equivalent ```plaintext &>>filename >>filename 2>&1 ``` #### Heredocs ```plaintext [n]<<[-]word ... word ``` #### Clobbering ```plaintext set -o noclobber # prevents >filename overwriting set +o noclobber # switches noclobber off echo override noclobber >| filename # overrides noclobber ``` ### Queries Are we being sourced ```plaintext if [ "${BASH_SOURCE[0]}" = "$0" ]; then echo source else echo run fi ``` ## History ```plaintext history # list all history items history | grep for # find history items containing 'for' !! # execute last command* !ls # execute last command starting with ls* !434 # run command numbered 434 from history !?hello? # run last command containing hello !?hello # run last command ending with hello sudo !! # run last command as root !1234:s/hello/world/ # command 1234, but with hello replaced by world ``` * Unless shell option `histverify` is set. ```plaintext Up/Down # go back/forward through history Alt+R # revert changes made to recalled command Ctrl+R # interactive reverse search Ctrl+O # run command matched in search Ctrl+G # exit search ``` ### Shell Options ```plaintext shopt -s histverify # ! recalls command but does not execute shopt -s dotglob # wildcard * matches entries beginning with . shopt -u dotglob # switch dotglob off shopt dotglob # show whether dotglob is on or off shopt # list all shell options and their status shopt -s extglob # enable extended globbing ``` ## Variables ### Prompt Set `PS1` to set your prompt. Examples: ```plaintext PS1='\u@\h:\w\$ ' PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' ``` The second of the above examples uses colours, whereas the first does not. To set colours, and other things, you use AnsiEscapeSequences. You use octal '\033' to write an escape character. For example ```plaintext \033[32m ``` selects green for subsequent text. When using AnsiEscapeSequences in the `PS1` variable, you need to surround them with `\[...\]` so that bash knows to ignore those characters when computing the number of //printed// characters in the prompt. (Deliberately neglect to do this and have a play, and you will see why it is necessary.) Variables you can use are: ```plaintext \u It is used to display the current username. \h It is used to the name of the computer name. \H It is used to the name of the hostname. \d It is used to display the date with weekday name, month name, and date. \w It is used to display the full path of the current working directory. \W It is used to display the last fragment of the current working directory. \t It is used to display the current time in 24-hour format. \T It is used to display the current time in 12-hour format. \@ It is used to display the current time in 12-hour format with AM/PM. \n It is used to add the new line. \e It is used to add an ASCII escape character. \v It is used to display the version of the bash. \V It is used to display the version of the bash with patch level. ``` My current prompt also sets the title on xterm and other terminals (for example the tab title in Windows Terminal). I put this in a file named `my_prompt` and source it from my `.bashrc`. ```plaintext BASE_PS1='\n\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\n\ set_term_title_prompt() { PS1="\[\033];\h:\w\007\]""$BASE_PS1" } unset_term_title_prompt() { PS1="$BASE_PS1" } set_term_title_prompt ``` The `\[\033];\h:\w\007\]` bit is what tells the terminal to set the tab title to `host:pwd`. ### Extended globs #### Examples ```plaintext shopt -s extglob echo "${@%%+(/aw/)}" # removing all trailing /'s ```