Learning Python and Bash: Week 2 – Mastering Shell Script Fundamentals


This week, I couldn’t work much on Python scripts or bash scripts, so I ended up practicing bash for a while, for which I will share the GitHub repo of all the code I created
I started revising my bash concepts. Realizing that most of the tasks that I was previously doing via Python script could be automated through bash scripts, and how much easier it is to write in bash. Here is a list of concepts I learnt regarding Bash Script
A bash script is a file containing a sequence of commands that are executed in order by the shell
Shell scripting is used for automation, system administration, and task scheduling
Adding variables in Shell
#!/bin/bash
name="John"
echo "Hello, $name!"
# O/P:
# Hello, John!
Command line arguments ($1, $2, ...)
#!/bin/bash echo "First argument: $1" echo "Second argument: $2" # run it ./myscript.sh Linux shell # O/P: # First argument: Linux # Second argument : shell
Conditional Statements
- If-else Statement
#!/bin/bash
if [$1 -gt 10 ]; then
echo "Number is greater than 10"
else
echo "Number is 10 or less"
fi
# Run:
./myscript.sh 15
# O/P:
# Number is greater than 10
Case statement
#!/bin/bash
echo "Enter a fruit name:"
read fruit
case $fruit in
apple) echo "You chose Apple";;
banana) echo "You chose Banana";;
*) echo "Unknown fruit";;
esac
Loops
- For loop
#!/bin/bash
for i in {1..5}; do
echo "Number : #i"
done
- While loop
#!/bin/bash
count=1
while [$count -le 5]; do
echo "Count: $count"
((count++))
done
Functions
#!/bin/bash
greet(){
echo "Hello, $1!"
}
greet "Alice"
Reading User Input
#!/bin/bash
echo "Enter your name:"
read name
echo "Hello $name!"
File Operations in Shell Script
# Check if a file exists
if [-f "myfile.txt"]; then
echo "File exists"
else
echo "File does not exist"
fi
# Append to a file
echo "New Line" >> myfile.txt
Scheduling Scripts with cron
- To turn a backup.sh every day at 2AM
0 2 * * * /path/to/backup.sh
- List scheduled cron jobs
crontab -l
Basic Shell Scripts
Input and Output of Script
if-then Scripts
for Loop Scripts
do-while Scripts
Case Statement Scripts
Check Remote Servers Connectivity
When working with remote servers , its important to check connectivity before performing any operations
- Using ping (Check if server is reachable)
ping -c 4 remote-server
# sends 4 pacjets to test if the server is reachable
# if the server is down, you'll see packet loss
- Using nc (Check if a specific port is open)
nc -zv remote-server 22
# Check if port 22 (SSH) is open on the remote server
# If successful, it will return "Connection Successful"
- Using telnet (Test port connectivity)
telnet remote-server 80
# Test if port 80 (HTTP) is accessible
# If connected, you'll see a blank screen; press CTRLL+ ], then type quit to exit
- Using ssh (Check if SSH works)
ssh -v user@remote-server
# Adds verbose mode (-v) to see SSH connection details
Using traceroute (see the path of the connection)
traceroute remote-server # shows each netwokr hop taken to reach the remote server
Aliases (alias)
These are shortcuts for frequently used commands
Create a Temporary Alias
alias ll="ls -lah"
# Now typing ll wil run ls -lah
# This alias is temporary (lost when you log out)
- Create a Permanent Alias
# add then to ~/.bashrc to ~/.bash_profile
echo "alias ll='ls -lah'" >> ~/.bashrc
source ~/.bashrc
#the alias will now persist across reboots
User and Global Aliases
- Each user can define aliases in ~/.bashrc or ~/bash_profile
nano ~/.bashrc
# Add:
alias gs="git status"
# Apply changes
source ~/.bashrc
## FOR SYSTEM WIDE OR GLOBAL ALIASES
nano /etc/profile
alias cls="clear"
# Apply changes
source /etc/profile
Shell History (history)
- shell keeps track of all executed commands
history
# shows recently executed commands
!100
# Run command no. 100 from history
history -c
# CLears the current session's history
history -d 101
# deletes a specific command number 101 from history
# SET how many commands to store
# By default bash keeps 500-1000 commands in history
# You can chagne this
export HISTSIZE=2000
export HISTFILESIZE=5000
# Saves 2000 commands in memory and 5000 in history file
Check Empty file
Using s (Checks if File is NOT Empty)
The -s operator checks if the file exists and has a size greater than 0 (not empty).
#!/bin/bash
file="example.txt"
if [ -s "$file" ]; then
echo "The file is NOT empty."
else
echo "The file is empty."
fi
✅ Best practice: Use -s when checking for non-empty files.
Using z "$(cat file)" (Checks if File is Empty)
The -z operator checks if a string is empty. Combined with cat, it checks if the file has content.
#!/bin/bash file="example.txt" if [ -z "$(cat "$file")" ]; then echo "The file is empty." else echo "The file is NOT empty." fi
⚠️ Downside: Uses cat, which is inefficient for large files.
Using wc -c (Checks File Size)
You can also use wc -c (word count, character count) to check if a file has 0 bytes.
#!/bin/bash file="example.txt" if [ "$(wc -c < "$file")" -eq 0 ]; then echo "The file is empty." else echo "The file is NOT empty." fi
✅ Best when you need an exact byte count.
Concepts
Specify the command Interpreter
the
#!
notation -. Shebang or hash-bang, starts the first line of script as an interpreter directive for bash syntax script files#!/usr/bin/bash
→ specify that the script must be executed using the bash shell located at the location/usr/bin/bash
What happens when you run a script?
OS Read Shebang
Interpreter Execution → OS uses the specified interpreter to execute the script
Options are applied → if options are specified, they are passed to the interpreter before the script is run
Without Shebang → if no shebang, the script might still work if you explicitly mention it with an interpreter
#!/usr/bin/bash -x
-x
→ tells bash to print each command before executing (for debugging)-e
→ exits immediately if any command fails to ensure the script stops execution upon encountering an error
If a filename is
-
Then, when you try tovim
orcat
it, it will not open, cause Linux thinks “- “ as stdin or stdout, not a filename, for it to interpret it as you wanting to open that file use,cat ./-
which $SHELL
→ Check what shell you are runningWhen you first launch the shell, it runs a startup script that is defined in
.bashrc
or.bash_profile
A shell script is run line by line
Positional arguments can be assigned using
$1 $2 $3
For other arguments, use
read
orread -p
Running in the background by adding
&
(ampercent) at the end of the commandcase statement
#!/bin/bash # | separator in case statement case ${1,,} in hearbert | administrator) echo "HELLO m you are the boss" ;; help) echo "JUST enter" ;; *) # catch all options echo "DEFAULT" esac
Array
Array ⇒
MY_LIST=(one two three four five)
if you just try
echo $MY_LIST
→ it will onyl return first elementto see the entire arary use
echo ${MY_LIST[@]}
for index →
${MY_LIST[1]}
function
sed
command
sed
→ stream line editor for real time editing in files or suing regular expressions
$0
- The filename of the current script.|$n
- The Nth argument passed to script was invoked or function was called.|$#
- The number of argument passed to script or function.|$@
- All arguments passed to script or function.|$*
- All arguments passed to script or function.|$?
- The exit status of the last command executed.|$$
- The process ID of the current shell. For shell scripts, this is the process ID under which they are executing.|$!
- The process number of the last background command.|
Trap
- It often comes the situations that you want to catch a special signal/interruption/user input in your script to prevent the unpredictables.
Trap is your command to try:
trap <arg/function> <signal>
trap "echo Booh!" SIGINT SIGTERM
echo "it's going to run until you hit Ctrl+Z"
echo "hit Ctrl+C to be blown away!"
while true
do
sleep 60
done
file tests commands
-e
→ to test if file exist-d
→ to test if directory exist-r
→ to check if the file has read permission for the user
#!/bin/bash
if [ -e "$filename" ]; then
echo "$filename exists as a file"
fi
if [ -d "$directory_name" ]; then
echo "$directory_name exists as a directory"
fi
if [ ! -f "$filename" ]; then
touch "$filename"
fi
if [ -r "$filename" ]; then
echo "you are allowed to read $filename"
else
echo "you are not allowed to read $filename"
fi
Process Substitution
Process substitution allows a process’s input or output to be referred to using a filename. It has two forms:
output
<(cmd)
,input
>(cmd)
.
Using diff file1 file2
could generate false positives in the case lines are not ordered. So if you want to compare those files you could create two new files, ordered, and compare those. It would look like:
# You can turn this
sort file1 > sorted_file1
sort file2 > sorted_file2
diff sorted_file1 sorted_file2
# into this
diff <(sort file1) <(sort file2)
Imagine you want to store logs of an application into a file and at the same time print it on the console. A very handy command for that is tee
.
# turn this
echo "Hello, world!" | tee /tmp/hello.txt
# to this (only lower case in the file and uppercase in output)
echo "Hello, world!" | tee >(tr '[:upper:]' '[:lower:]' > /tmp/hello.txt)
sort
command
The
sort
command in Linux is a utility used to sort lines of text files or standard input. By default, it sorts lines alphabetically in ascending order-r
→ Reverse sort-n
→ numeric sort-u
→ remove duplicate-k
→ sort by specific field/column-t
→ Specify field separator>
or-o
→ save output to new file-c
→ check if sorted
Python and Bash scripts for learning different real-life use cases in Linux: Github Link
Subscribe to my newsletter
Read articles from MRIDUL TIWARI directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

MRIDUL TIWARI
MRIDUL TIWARI
Software Engineer | Freelancer | Content Creator | Open Source Enthusiast | I Build Websites and Web Applications for Remote Clients.