OS Shell Scripting DarkMode
OS Shell Scripting DarkMode
Analogy: The OS kernel is like a powerful engine inside a car. You do not control the engine directly
— you use the steering wheel and pedals. The shell is that interface: it translates your
human-readable commands into precise instructions the engine can act on.
#!/bin/bash
# This is ALWAYS the first line of every Bash script.
# The #! tells the OS: 'use the program at this path to run this file'.
# Without it, the OS doesn't know HOW to interpret the script.
Variables
The most critical rule: no spaces around the = sign when assigning. Writing num = 42 is wrong in Bash
— it tries to run a command called 'num'.
Reading User Input
a=10 ; b=3
echo $((a + b)) # Addition: 13
echo $((a - b)) # Subtraction: 7
echo $((a * b)) # Multiplication: 30
echo $((a / b)) # Division: 3 (integer — remainder dropped)
echo $((a % b)) # Modulo: 1 (remainder of 10 ÷ 3)
Conditionals — if [ ] and (( ))
Loops
#!/bin/bash
echo "Enter a number:"
read num
# Numbers <= 1 are never prime — handle this edge case immediately
if [ $num -le 1 ]
then
echo "Not Prime"
exit # Stop the entire script right here
fi
# Try every possible divisor from 2 up to num/2
for (( i=2; i<=num/2; i++ ))
do
if [ $((num % i)) -eq 0 ] # If remainder is 0, i is a factor
then
echo "Not Prime"
exit # Found a factor — no need to check further
fi
done
# If we reach this line, no factor was ever found
echo "Prime"
#!/bin/bash
echo "Enter a year:"
read year
# (( )) lets us use natural operators: || = OR, && = AND, == and !=
if (( (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0) ))
then
echo "Leap Year"
else
echo "Not a Leap Year"
fi
Start 121 — 0 —
1 121 1 0×10+1 = 1 12
2 12 2 1×10+2 = 12 1
3 1 1 12×10+1 = 121 0
Bug in original: Q3 and Q5 in your assignment use capitalised keywords like Echo, While, Do, If,
Fi. Bash is case-sensitive — these must be lowercase. The corrected version is below.
#!/bin/bash
echo "Enter a number:"
read num
original=$num # Save a copy BEFORE the loop destroys $num
reverse=0
while [ $num -gt 0 ]
do
digit=$((num % 10)) # Extract last digit
reverse=$((reverse * 10 + digit)) # Prepend digit to reverse
num=$((num / 10)) # Remove last digit from num
done
if [ $original -eq $reverse ]
then
echo "Palindrome"
else
echo "Not Palindrome"
fi
Part 4: Script 4 — Armstrong Number Check
#!/bin/bash
echo "Enter a number:"
read num
original=$num # Save before loop modifies num
sum=0
while [ $num -gt 0 ]
do
digit=$((num % 10)) # Extract last digit
sum=$((sum + digit*digit*digit)) # Add cube of digit to sum
num=$((num / 10)) # Remove last digit
done
if [ $sum -eq $original ]
then
echo "Armstrong Number"
else
echo "Not an Armstrong Number"
fi
Start 153 — — 0
1 153 3 27 27
2 15 5 125 152
3 1 1 1 153
#!/bin/bash
echo "Enter number of terms:"
read n
a=0 # First Fibonacci number
b=1 # Second Fibonacci number
echo "Fibonacci Series:"
for (( i=1; i<=n; i++ ))
do
echo -n "$a " # -n suppresses the newline, stays on same line
temp=$((a + b)) # Calculate NEXT term BEFORE overwriting a
a=$b # Shift a forward
b=$temp # Shift b forward to the new next term
done
echo # Final newline after all terms are printed
1 0 0+1=1 1 1
2 1 1+1=2 1 2
3 1 1+2=3 2 3
4 2 2+3=5 3 5
5 3 3+5=8 5 8
Part 6: Script 6 — Decimal to Binary Conversion
1 13 1 "1"
2 6 0 "01"
3 3 1 "101"
4 1 1 "1101"
#!/bin/bash
echo "Enter a decimal number:"
read num
binary="" # Start with an empty string
while [ $num -gt 0 ]
do
rem=$((num % 2)) # Remainder is either 0 or 1
binary="$rem$binary" # PREPEND: new bit goes to the LEFT of existing bits
num=$((num / 2)) # Integer division strips the last bit
done
echo "Binary number: $binary"
Prepend not append: The division algorithm produces bits from least-significant (rightmost) to
most-significant (leftmost). By writing "$rem$binary" instead of "$binary$rem", we automatically
build the number in the correct left-to-right order.
Part 7: Complete Viva Questions & Answers
Every angle an examiner might probe — from basic syntax to deep logic traps. Questions are ordered from
basic to advanced within each category.
A: A shell script is a text file containing a sequence of shell commands that the Bash interpreter
executes line by line. It automates repetitive tasks without compiling.
A: It is called a shebang. The #! tells the OS this is a script file, and /bin/bash is the path to the
interpreter. Without it, the OS does not know how to run the file.
A: Double quotes allow variable expansion — $name is replaced by its value. Single quotes treat
everything literally — $name prints as the text '$name'.
A: read pauses the script, waits for user input, and stores what is typed into the named variable.
A: Square brackets [ ] use flag syntax: -eq, -lt, -gt etc. for numbers and = for strings. Double
parentheses (( )) use natural arithmetic operators: ==, <, >, &&, || — more natural for mathematical
conditions.
A: The -n flag suppresses the newline that echo normally adds, so the next output appears on the
same line. The Fibonacci script uses this to print all terms on one line.
Q: Why are Bash keywords case-sensitive?
A: Bash follows Unix conventions where all identifiers are case-sensitive. The interpreter only
recognises if, then, while, do, done, fi in lowercase. Writing 'If' causes Bash to search for a command
named 'If', which does not exist.
Q: Why does the prime script check up to num/2 and not num?
A: If N has a divisor d greater than N/2, then N/d would be less than 2, which is impossible for integer
divisors. So no factor of N can be larger than N/2, halving the work needed.
A: 2 passes the >1 check. The loop runs for i=2 to 2/2=1 — since 2 > 1, the loop never executes.
The script reaches the final echo and correctly prints Prime.
A: It directly implements the Gregorian calendar rule. The first part handles century years divisible by
400 (always leap). The second handles regular years: divisible by 4 but not 100. 1900 fails because
it is divisible by 100 but not 400.
A: The while loop divides $num by 10 repeatedly until it becomes 0. We need the original value to
compare at the end, so we save a copy before the loop begins.
A: temp stores a+b before we overwrite a. Without it, writing a=$b first would corrupt the sum
calculation on the next line. temp is the classic safe-swap variable.
A: Division by 2 produces the least significant bit first. Prepending places each new bit to the left of
all previous bits, which naturally builds the correct binary order.
A: 10%2=0, binary='0', num=5. 5%2=1, binary='10', num=2. 2%2=0, binary='010', num=1. 1%2=1,
binary='1010', num=0. Output: 1010.
Category C — Mathematics & Edge Cases
A: The while condition [ $num -gt 0 ] is immediately false. The loop never runs, reverse stays 0,
original is 0. Since 0 == 0, the script prints Palindrome — which is reasonable.
A: The while loop never executes, binary stays an empty string. The script prints 'Binary number: '
with nothing after it. A production script would add a special case for 0.
A: O(N/2) which simplifies to O(N). A more efficient version checks up to √N giving O(√N), but the
N/2 approach used here is sufficient for this lab's scope.
A: Bash assigns the literal string 'num+1' to the variable — no arithmetic happens. This is the most
common beginner Bash mistake. All arithmetic must be inside $(( )).
A: The command fails because Bash looks for a command literally called 'if[$num'. Square brackets
require spaces on all sides: [ $num -eq 0 ].
A: Both scripts use capitalised keywords: Echo, Read, While, Do, Done, If, Then, Fi. Bash only
recognises these in lowercase — capitalised versions cause 'command not found' errors.
A: First make it executable: chmod +x [Link]. Then run it: ./[Link]. Alternatively bypass
permissions with: bash [Link]
Part 8: Quick Revision Cheat Sheet
Prime Divide by i=2..N/2; any % modulo Use exit not break; handle ≤1
remainder=0 → not prime edge case
Leap Year Div by 400 OR (div by 4 AND || and && 1900 is NOT a leap year
NOT div by 100)
Palindrome Reverse digits via %10 loop; % 10 and / 10 Save original before loop; use
compare to original lowercase
Armstrong Sum digit³ via loop; compare to digit*digit*digit Only correct for 3-digit numbers
original as written
Fibonacci Print a; temp=a+b; a=b; b=temp; Swap via temp temp prevents overwrite bug;
repeat n times echo -n inline
Dec→Binary Collect remainders of ÷2; Prepend $rem$bin Prepend not append; 0 edge
prepend each to string case unhandled
Final viva tip: For every script, be ready to: (1) explain the mathematical concept in plain English,
(2) trace through a specific example by hand step-by-step, and (3) explain why each line of code is
written the way it is. Examiners love 'what would happen if...' questions — all answers are in
Category D above.