Bash Shell Scripting
What are Shell Scripts?
- Files containing a series of commands
- In other OSs they have the .sh extension
- A shell is a program that passes commands to the operating system
- You interact with the shell using the CLI
- Shells and command languages are also scripting languages
-
- You can write programs in Bash to be interpreted and executed by the shell
- Before we start writing shell scripts, let's get used to a few awesome Bash concepts
Bash Tips
-
Your ~/.bashrc file gets read and its commands are applied whenever you start a shell session
- This is where you'll put your settings and any shell functions (more on that later)
-
export EDITOR=/usr/bin/vim
-
bind "TAB:menu-complete"
-
bind "set show-all-if-ambiguous on"
-
bind "set completion-ignore-case on"
- When writing long commands, you can hold Control and press 'x' then 'e' to edit the command in Vim
- Ctrl+l to clear the terminal screen
-
!! is the last run command
- Ex. sudo !! runs the last command as sudo (if you forgot to do so)
Control Operators
-
; runs commands sequentially
-
command1 ; command2
-
-
& runs commands in the background
-
command1 & command2
-
-
&& runs one command after another has successfully executed
-
command1 && command2
- AND operator
-
-
|| runs one command after another fails
-
command1 || command2
- OR operator
-
Can also be written as an if else statement
-
echo & shell stuff
- echo is a command that prints out its arguments into the command line
- When you press Enter/Return, the shell translates whatever is typed in before it is interpreted. Try these:
-
echo hello world
-
echo *
-
-
* is an expansion that matches all characters in a filename, the shell doesn't literally read it as *, it reads it as the wildcard expansion results
-
echo ~/*
-
Expansions
- Expansions are character sequences that are changed before the shell acts on it
-
$((arithmetic expression))
-
echo $(((5*5)+10)) is equal to 35
-
-
Brace expansion is great for working on multiple character sequences and files
- Separate the different arguments in the curly braces with commas and NO SPACES
- You can use .. to produce a range of numbers/letters
-
echo front-{A..D}-back
-
echo number{1..7..2}
-
touch {john.py,irene.py,yukio.py}
-
rm {john,irene,yukio}.py
-
More Shell Stuff
-
Parameter expansion uses variables for Bash
- Use the printenv command to see environment variables
- Variables are denoted with a $
-
echo $USER
-
echo $PATH
-
The PATH variable is very important! You'll see why soon
-
-
- Command substitution allows you to use a command's output as an expansion
-
$(command)
-
echo $(ls)
-
sudo pacman -R $(pacman -Qdtq)
-
Writing Shell Scripts
- The first line of every shell script should be a shebang (#!)
- Tells the shell which interpreter to use
-
#!/bin/bash
- Like Python, you comment lines in Bash with #
- Not to be confused with #!
- Let's write our first simple shell script: hello_world
#!/bin/bash
echo "Hello World!"
Executing Shell Scripts
- Before we run our shell script, we have to make it executable
- Remember file permissions? ls -l
-
chmod +x hello_world
- You could also use the octal modes 755 or just 700
- Now let's run our script!
-
./hello_world
- The "./" is writing out the relative path, . denotes the current directory
-
Script Location
- Why did we have to write the path instead of just typing in hello_world?
- Remember the PATH environment variable?
-
echo $PATH
-
- Whenever you execute a command, the shell searches through the directories in the PATH variable for an executable program. Having the path written out gives the system the file
- Remember the PATH environment variable?
- If you don't want to have to write the path, you can move the script into one of those directories (like /bin or /usr/bin), or add a directory to your $PATH
Adding Paths to $PATH
- You can either add the path to the beginning or end of the PATH variable
- The order matters for which directories get searched first
- Add to your .bashrc:
-
export PATH=/path/you/want:$PATH
-
export PATH=$PATH:/path/you/want
-
Variables
- Like Python, Bash creates variables as they are encountered during assignment
-
variable=value
- No spaces!
- Call the variable how you normally would in Bash
- Unless specified otherwise, all data in variables are stored as strings
#!/bin/bash
title="Detailed Contents of Directory"
stuff=$(ls -alh)
echo "$title
$stuff"
Here Documents
- Another way to output text other than echo is using a here document
- Embeds a body of text into the script and feeds it to the standard input using redirection
-
command << token
-
text
-
token
-
-
command is a command that accepts stdin (like cat) and token is a string that's used to indicate the end of the text
- _EOF_ is usually used as a token, meaning end of file
- Embeds a body of text into the script and feeds it to the standard input using redirection
- Pretty much the same as echo, except single and double quotes aren't expanded and lose their meaning to the shell
Here Documents
#!/bin/bash
title="Detailed Contents of Directory"
stuff=$(ls -alh)
cat << _EOF_
$title
"Here is a list of"
'the contents of the pwd'
yay!
$stuff
_EOF_
# Change the redirection operator to <<- if you
# want to ignore leading tabs for formatting
Scripting Review Exercise
Create a script that generates a System Information Page. The page should display a timestamp of when it was created (and by who), the shell you're using , how long the computer has been on, and disk space usage.
- Use a here document
- Use the following variables:
- $USER, $SHELL
- Create 2 of your own
- Use the following commands:
- df -h
- date
- uptime -p
- For the HTML: Use <h1>, <h2>, <p>, and <pre> tags
<!--The HTML skeleton-->
<html>
<head>
<title></title>
</head>
<body>
page content
goes here
</body>
</html>
Shell Functions
- Shell functions are like functions in Python, except they're written as "miniscripts" located inside of scripts that can act as programs
- There are 2 different ways to define functions
function name {
commands
return
}
name() {
commands
return
}
# call functions by
# writing the name
name
- name is the name of the function
- commands is the series of commands executed by the function
- return is optional
- Local variables are defined with the keyword local preceding the name
Function Positional Parameters
- Shell functions can take in command line arguments
- Use the variables $1, $2, $3, ..., $n to access the arguments based on its position
- Call the function like so: functionName foo bar
- foo is the first argument that is stored in $1
- bar is the second argument that's stored in $2
- Special variables:
- $0 holds the command/function name
- $* or $@ holds all parameters/arguments passed to the function
- $# holds the number of positional parameters passed to the function
Shell Functions in your .bashrc
- Shell functions can be written in your .bashrc to be executed as commands
- Great replacement for aliases
- Aliases are limited in shell features, functions are not
-
Useful Exercise:
- Write a function cd() in your .bashrc that automatically executes ls whenever you cd into a directory
- Hint: Use the builtin keyword so your function isn't recursive and runs forever
- Since your .bashrc is read whenever you start a new shell session, you have to open a new terminal or source the file to use your new function
-
source ~/.bashrc
-
read
-
read is a built-in command that reads a single line of keyboard input and stores it in a variable(s) that's passed in as an argument
-
read [-options] [variables]
- A lot of the options are really useful, look them up!
-
#!/bin/bash
echo -n "Please enter a word: "
read word
echo $word
test
- The best command to use with if statements (covered next) is test
-
[ expression ]
-
test expression
- expression is an expression that's evaluated as either true or false
-
- Check the manual for test to see how to use it!
-
man test
- Test equality/inequality in strings and integers
- Evaluate the status of files
-
if Statements
# Syntax of if statements
if commands; then
commands
elif commands; then
commands
else
commands
fi
python=5
if [ $python == 5 ]; then
echo "Python is cool"
elif [ $python == 6 ]; then
echo "Python isn't cool"
else
echo "C is annoying"
fi
- commands is a list of commands
- You can also enter it directly into the command line with ; as the newline separator (not after the then though)
- The shell evaluates the success or failure of a command through the exit status
Exit Status
- When a command (or shell function/script) finishes executing and terminates, it issues an integer in the range of 0 to 255 to the system called the exit status
- 0 indicates success
- Any other number (1-254) indicates failure
- The variable $? holds the value of the exit status
- The commands true and false always terminate with a 0 and 1 exit status, respectively
-
true
-
echo $?
-
false
-
echo $?
-
Scripting Review Exercise
Write a shell script that takes gives the user 5 seconds to enter a number, and then prints out whether that number is even or odd
Write a function for the above shell script that requires the user to input a predefined password to use the script
Other ways to use test
- A more modern, enhanced replacement for test
-
[[ expression ]]
- Supports all test expressions/arguments, but has a couple of additions
-
string =~ regex where regex is an extended regular expression; used for data validation
-
The == operator supports pathname expansion *
-
-
- Operate on integers with (( ))
- Performs arithmetic truth tests
-
Ex. if ((INT == 0)); then echo "INT is zero"; fi
-
- Performs arithmetic truth tests
- Combine expressions using the && and || operators
- ! is the NOT operator
Bash Shell Scripting
By jtheadland
Bash Shell Scripting
- 638