Shell

Terminal Emulator

Types of shells

Bourne Shell Family

  • Standard scripting
  • sh
    • Bourne Shell
    • original Unix shell
    • lightweight and feature poor
  • bash
    • Bourne-Again Shell
    • Adds features like command history and arrow-key navigation
  • zsh
    • Z Shell
    • Highly polished and modern upgrade to bash
    • Adds advanced tab completion, theme frameworks, automatic spelling correction
  • dash
    • Debian Almquist Shell
    • Ultra-fast sh clone
    • used to execute background system scripts

C Shell Family

  • Interactive but legacy
  • csh
    • C-like syntax for scripting

Modern shells

  • fish
    • Friendly Interactive Shell
    • Non-POSIX shell
    • focused entirely on interactive user experience

List Supported Shells

cat /etc/shells

View Current Shell

  • Not as straightforward
  • SHELL variable is misleading
# if not launched from script
echo $0

Change shell

  • Current Shell
# launches zsh shell as child process
zsh
  • Default Shell
    • It modifies /etc/passwd file internally
    • Need to logout and login to take effect
# changes new login shell for the user account
chsh -s /usr/bin/zsh

Config for current shell

  • shopt: configure options for bash
  • setopt: configure options for zsh
  • set: configure options in shell agnostic way
    • Syntax Rule
      • - enables feature
      • + disables feature
    • set -o: List all options
    • set -e: Enables “exit on error”
      • Instantly terminates the script if any command fails
    • set -u: Enables “nounset” (“No Unset”)
      • Treats unset or missing variables as an error and halts execution immediately instead of expanding them to empty strings
    • set -x: Enables xtrace/debug
      • Prints every command to the screen exactly as it expands before executing it. This is the standard tool for shell debugging

Current Directory

pwd

Change Directory

# relative to current directory
cd bin
 
# relative path
cd ../bin
 
# absolute path
cd /usr/bin
 
# change to home directory
cd
 
# prev working directory
cd -
 
# change to bob's home directory
cd ~bob

pushd and popd

  • Both are shell commands
  • The pushd command is used to save the current directory into a stack and move to a new directory. If no directory is specified, pushd changes the directory to whatever is on the top of the stack.
    • syntax: pushd <directory>
  • popd can be used to return back to the previous directory that is on top of the stack.
    • syntax: popd
  • examples:
root@e154689b500f:/home# pushd /usr/bin
/usr/bin /home
root@e154689b500f:/usr/bin# popd
/home
root@e154689b500f:/home#

Clear terminal

  • Shortcut: Ctrl + L
clear

exit terminal

exit

History of Shell

  • Saved in ~/.bash_history or ~/.zsh_history
# show 100 entries of history
history 100
 
# path to history file
echo $HISTFILE
 
# size of history
echo $HISTSIZE
  • Running historical command
    • easier to use arrow keys
# Run previous command
> !!
 
# Run nth command from history
!n
  • Press Ctrl + R
    • search command history
    • press again to move to next occurrence
  • Esc then .
    • Pulls previous command argument

Special Shell Parameters

# Return code for last command
# You can only use it once, because after running
# echo itself will return 0
echo $?
 
# PID of last job run in background
echo $!
 
# PID of current shell or script
echo $$
 
# filename of current script or name of shell
echo $0
 
# number of args passed to script
echo $#
 
# positional params passed as argument
echo $1
echo $2
echo $3
...
 
# all of positional params
echo $*
 
# all of positional params with each parameter as quoted string
echo $@
 
# arguments of previous command
echo $_

Keyboard Shortcuts

  • Terminal Signals
    • Ctrl + C —> SIGINT
    • Ctrl + \ —> SIGQUIT
    • Ctrl + Z —> SIGTSTP
  • Clipboard
    • Ctrl + Shift + C —> Copy
    • Ctrl + Shift + V —> Paste
  • Line Editing and Cursor navigation
    • Ctrl + A —> Go to start
    • Ctrl + E —> Go to end
    • Ctrl + W —> Delete last word
    • Ctrl + U —> Wipe entire line
  • History
    • —> previous commands in history
    • —> next command in history
    • Ctrl + R
      • search command history
    • Tab —> completion
    • Tab + Tab —> list of possible completions
    • Esc then . —> Pull the last argument/path from your previous command into the current prompt
  • Ctrl + L —> Clear screen
  • Ctrl + D
    • Send EOF (End of File) marker
    • Closes terminal emulator session

Prompt

  • Generally of the form: username@machinename <current directory>$
  • If the last character is # instead of $ then the terminal session has superuser privileges
  • controlled by PS1 environment variable
root@9f1bd04a4244:/usr/bin# echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
  • PS1: Primary prompt
  • PS2: Continuation prompt
    • used when you forget to close quotes ' or "
  • PS3: Select Loop prompt
  • PS4: Debugging execution prompt
    • used when trace debugging enabled

Completion

  • Completion (Tab)
    • pathnames
    • variables (starting with $)
    • usernames (starting with ~)
    • hostnames (starting with @)
  • List of completions
    • Tab + Tab
  • Programmable completion
    • completion rules can be added
    • implemented using shell scripts
    • use cases
      • option list of a command
      • match particular file types

Shell expansion

  • https://man7.org/linux/man-pages/man1/bash.1.html#EXPANSION

  • Every time we type a command and press enter, shell performs expansion before carrying out the command

  • This is order in Bash Shell expansion

    1. Brace expansion
    2. Tilde expansion
    3. Parameter and variable expansion
    4. Arithmetic expansion
    5. Command substitution (done in a left-to-right fashion)
    6. Word splitting
    7. Pathname expansion
    8. Quote removal
  • Process substitution is performed parallelly with tilde/param and var/arithmetic/command substitution

  • Brace expansion

> echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back
 
> echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
 
> mkdir {2007..2009}-{01..12}
2007-01 2007-02 2007-03 2007-04 .....
.... 2009-09 2009-10 2009-11 2009-12
  • Tilde expansion
# prints home directory
> echo ~
/home/me
 
> cd ~bob
/home/bob
  • Parameter and variable expansion
# prints value of USER variable
> echo $USER
me
 
# null coalescing
# prints value if it exists else default
> echo ${JAVA_HOME:-/opt/jdk/jdk-11}
 
# assign value if it does not exist
> echo ${JAVA_HOME:=/opt/jdk/jdk-11}
 
# crash script with custom error message
> echo ${JAVA_HOME:?"JAVA_HOME not set"} 
 
# use alternative value
# if JAVA_HOME set, then update to new path
> echo ${JAVA_HOME:+/opt/jdk/jdk-11}
  • Arithmetic expansion
echo $((2 + 2))
  • Command substitution
# prints cp binary details
ls -l $(which cp)
  • Process substitution
> cat <(echo "foo")
foo
 
> echo <(echo "foo")
/dev/fd/63
 
> echo >(echo "foo")?????
  • Word Splitting
> echo hello    world
hello world
  • Pathname expansion
    • By default hides hidden folders/files starting with dot
# replace * with list of all files and then echo prints it
echo *
 
# prints all files starting with D
echo D*
  • Quote removal
    • Removes all quotes, double quotes and backslashes

Suppressing expansion

  • expansion can be suppressed using quotes
# without quotes, performs all expansions
> echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
 
# double quotes suppress tilde, pathname, braces expansion
> echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
 
# suppresses all of expansion
> echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
  • Enable interpretation of backslash escapes using -e
# Without -e (prints literally)
> echo "Hello\nWorld"
Hello\nWorld
 
# With -e (creates a new line)
> echo -e "Hello\nWorld"
Hello
World

Record your terminal

script record.txt
 
<do your work in terminal>
 
# send EOF using Ctrl+D to stop recording