Shells

Last edited

What is a shell?

What is it? A shell is a user-space program that reads text, expands it and executes programs, wiring up their file descriptors.

What is it really? A shell is a program that implements the POSIX spec that defines the interface and how it behaves.

zsh, bash, sh, etc. all implement the common core requirements of the POSIX spec, that way your commands (operators, snytax) run on all of them.

POSIX Shell Spec

Note

Meaning of the name Shell: The word originally meant an outer shell around commands. People also say the outer shell around the kernel.

What is sh?

  • sh stands for shell, more specifically bourne shell.
  • sh original shell that shipped with Unix in 1977 - contrast bash was written 10 years later for GNU to be an OSS version of sh
  • sh is both an interactive command interpreter and a scripting language - scripts are just commands saved to a file and run through the same interpreter
  • you should always write scripts targeted for sh because it is the baseline and ensures your scripts will run other systems, rather than relying extra features from other shells

Execution

Shebang

Minimal example of a sh script:

Shell
#!/bin/sh
echo "hello world"
  • The kernel looks for the syntax in the first line (shebang) and decides how to execute the the file
  • The shell this spawns only sees this as comment
  • shebang: #! path to interpreter:/bin/sh

If you need your script to run as another interpreter use:

#!/usr/bin/env bash
#!/usr/bin/env ruby

Source

Source is useful for setting envrionment variables or customizing the current shell

Pithy

source just doesn’t fork() when it runs the commands

Bash
sh helloworld     # runs in a new instance of sh
source helloworld # uses current shell to execute the commands

Variables

Exported variables

When you run:

export HELLO="world"

The shell does the following

  1. looks up up HELLO
  2. adds it if doesn’t exist
  3. sets the value to world
  4. sets the boolean flag exported
# Table of shell variables
Name    Value    Exported
----    -----    --------
HELLO   world    yes        # envrionment variable (passed to child)
PS1     ...      no         # shell variable (not passed down)

An exported variable just means it will be passed into the child shell.
So if you export a variable and run a script that reads environment variables only exported variables will be passed in.

Variables and quoting

Omit spaces around the = symbol; otherwise, the shell mistakes your variable name for a command name and treats the rest of the line as a series of arguments to that command.

etcdir='/etc'
echo $etcdir
# single quotes = string literals, no variable expansion
echo '$HOME' # = $HOME
# double quotes will expand variables
echo "$HOME" # = /home/mat

Curly braces when referencing a variable

You can surround its name with curly braces to clarify to the parser and to human readers where the variable name stops and other text begins

The braces are not normally required, but they can be useful when you want to expand variables inside double-quoted strings. Often, you’ll want the contents of a variable to be followed by literal letters or punctuation.

${etcdir}   # instead of $etcdir
echo "${file}s"        # without braces, shell reads $files (wrong variable)
echo "${name^}"        # capitalize first letter

Arguments

$# # number of arguments supplied
$* # all arguments at once

# check if there's an argument
if [ $# -ne 2 ]; then
    exit 1

~/.bash_profile or ~/.profile for functions you want available as commands in every interactive shell session.

Control Flow

Comparison Operators

StringNumericTrue if
x = yx -eq yx is equal to y
x != yx -ne yx is not equal to y
x < yx -lt yx is less than y
n/ax -le yx is less than or equal to y
x > yx -gt yx is greater than y
n/ax -ge yx is greater than or equal to y
-n xn/ax is not null
-z xn/ax is null

Evaluation Operators

OperatorTrue if
-d filefile exists and is a directory
-e filefile exists
-f filefile exists and is a regular file
-r fileUser has read permission on file
-s filefile exists and is not empty
-w fileUser has write permission on file
file1 -nt file2file1 is newer than file2
file1 -ot file2file1 is older than file2

Loops

Shell
for script in rhel.sh sles.sh; do
    echo "Running $script"
    bash "$script"
done

# read splits on env var IFS (internal field seperator)
# IFS=\n
while read line; do
    echo "$((counter++)): $line"
done

Exec

Exec command has the following uses:

Replaces the current shell with a command (no new process)

Shell
exec /bin/bash

Redirects file descriptors (exec < file, exec > file, exec 2>&1)

Shell
exec < input.txt
exec > output.txt
exec 2>&1

Grep

TODO: grep cheatsheet, explain defaults

grep --ignore-case # -i