Most important module
- [what are scripts](#what\ \is\ a\ \script)
- shebang
- variables
- tests
- decisions
- [for loops](#for\ loops)
- accept cli arguments
- accept input
What is a script
- contains a series of commands
- commands are interpreted by an interpreter
- anything you can do in terminal you can do in a script
- great for automating tasks
eg.
#!/bin/bash
echo "Scripting is fun!"> chmod +x script.sh
> ./script.shShebang
the #! in #!/bin/bash can be read as sharp bang which is weirdly abbreviated to shebang
the remaining gives the path to interpreter used to interpret the script
basically what happens is
> /bin/bash ./script.sh
or
> /bin/ksh ./script.sh
or whatever interpreter you use is being called to execute your script
you can check this with ps -fp <pid> and go deeper with pstree -p <pid>
command interpreters can be
bash, python, zsh, fish or whatever
Variables
Syntax:
VARIABLE_NAME="Value"no space before and after the ”=”
to use the variable do either
$MY_VARIABLE or ${MY_VARIABLE}
eg
#!/bin/bash
MY_SHELL="bash"
echo "I am ${MY_SHELL}ing on my keyboard" # here you need to put it in curly braces>> I am bashing on my keyboard
you can assign the output of a command to a variable
eg
#!/bin/bash
SERVER_NAME=$(hostname)
echo "You are running this sript on ${SERVER_NAME}"enclose the command in parantheses or backticks
i.e. SERVER_NAME=$(hostname) or SERVER_NAME=`hostname`
names can not
- start with numbers
- contain symbols except for ’_‘
Tests
Syntax:
[ condition-to-test-for ]
example:
[ -e /etc/passwd ] # checks if /etc/passwd exists
go through the man page for test for more info
> man test
common tests are
| test | desc |
|---|---|
-d FILE | true if file is a directory |
-e FILE | true if file exists |
-f FILE | true if file exists and is a regular file |
-r FILE | true if file is readable by user |
-s FILE | true if file exists and is not empty |
-w FILE | true if the file is writeable |
-x FILE | true if the file is executable by you |
-z STRING | true if string is empty |
-n STRING | true if string is not empty |
STRING1 = STRING2 | true if strings are not equal |
STRING1 != STRING2 | true if strings are not equal |
arg1 -eq arg2 | arg1 = arg2 |
arg1 -ne arg2 | arg1 != arg2 |
arg1 -lt arg2 | arg1 < arg2 |
arg1 -le arg2 | arg1 ⇐ arg2 |
arg1 -gt arg2 | arg1 > arg2 |
arg1 -ge arg2 | arg1 >= arg2 |
Decisions
the if statement
if [ condition-is-true ]
then
command 1
command 2
fi#!/bin/bash
MY_SHELL="bash"
if [ "$MY_SHELL" = "bash" ]
then
echo "why don't you use fish???"
fiif-else statements
if [ condition-is-true ]
then
command N
else
command M
fieg
#!/bin/bash
MY_SHELL="fish"
if [ "$MY_SHELL" = "fish" ]
then
echo "good choice!!!"
else
echo "use fish bruh"
fiif-elif-else
if [ condition-is-true ]
then
command N
elif [ condition-two ]
then
command M
else
command X
fiFor Loops
Syntax:
for VARIABLE_NAME in ITEM_1 ITEM_2
do
command 1
command 2
command N
doneeg
#!/bin/bash
for COLOR in red green blue
do
echo "$COLOR"
done>> red
>> green
>> blue
items can be in a list
eg
#!/usr/bin/bash
COLORS="red green blue"
for COLOR in $COLORS
do
echo "$COLOR"
done>> red
>> green
>> blue
script to rename files
eg
#!/usr/bin/bash
PICTURES=$(ls *jpg)
DATE=$(date +%F)
for PICTURE in $PICTURES
do
echo "Renaming ${PICTURE} to ${DATE}-${PICTURE}"
mv $PICTURE ${DATE}-${PICTURE}
done> ls *jpg
>> bear.jpg man.jpg pig.jpg
> ./rename-pics.sh
>> Renaming bear.jpg to 2024-09-24-bear.jpg
>> Renaming man.jpg to 2024-09-24-man.jpg
>> Renaming pig.jpg to 2024-09-24-pig.jpg
Positional Parameters
> ./script.sh parameter1 parameter2 parameter3
$0: "./script.sh"
$1: "parameter1"
$2: "parameter2"
$3: "parameter3"up $9
eg
#!/bin/bash
USER=$1
echo "Executing script: $0"
echo "Archiving user: $USER"
# Lock the account
passwd -l $USER
# Create an archive for ~/
tar cf /archives/${USER}.tar.gz /home/${USER}
$@accesses all parameters from$1to the end
eg
#!/bin/bash
echo "Executing script: $0"
for USER in $@
do
echo "Archiving user: $USER"
passwd -l $USER
tar cf /archive/${USER}.tar.gz /home/${USER}
doneAccepting Input
Syntax:
read -p "PROMPT" VARIABLE
accepts STDIN - Standard Input
eg
#!/bin/bash
read -p "Enter a user name: " USER
echo "Archiving user: $USER"
# Lock the account
passwd -l $USER
# Create an archive for ~/
tar cf /archives/${USER}.tar.gz /home/${USER}Reading File Contents in Bash
read command
read: read [-Eers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descriptor FD. if the -u option is supplied. The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on, with any leftover words assigned to the last NAME. Only the characters found in $IFS are recognized as word delimiters. By default, the backslash character escapes delimiter characters and newline.
If no NAMEs are supplied, the line read is stored in the REPLY variable.
Options:
-r do not allow backslashes to escape any charactersSimple Example:
# Read from the file file.txt and output the tenth line to stdout.
i=0
while read -r line; do
(( i++ ))
if [ $i -eq 10 ]; then
echo $line
fi
done < "file.txt"my solution to Leetcode 195