Shell Scripting : Day #1

Shell Scripting : Day #1

Ahoy sailors! This time we onboard the sail and take on a voyage to explore the realms of THE SHELL...

This blog post summarizes the first lecture of the "Missing Semester" course, focusing on the shell and its functionalities. You may find the link for Lecture 1 here: https://missing.csail.mit.edu/2020/course-shell/

Why the Shell?

Graphical interfaces are convenient, but they limit what you can do. The shell offers a powerful way to interact with your computer directly. And, to sum it up all, I'd say that to take full advantage of the tools your computer provides, we have to go old-school and drop down to a textual interface: The Shell.

What is the Shell?

In the context of computers, a shell is a program that acts as an interface between the user and the operating system. It provides a way to communicate with the operating system by issuing commands and receiving feedback. There are two main types of shells:

  1. Command-Line Shell (CLS): This is a text-based interface where you type commands and see text output. It's considered the traditional way to interact with the system, especially for power users and system administrators. Bash (Bourne Again SHell) is a common example of a CLS found on Linux and macOS systems.

  2. Graphical Shell (GUI Shell): This is the more user-friendly interface most people are familiar with today. It uses windows, icons, menus, and other visual elements to interact with the operating system. The Finder on macOS and File Explorer on Windows are examples of GUI shells.

Here's a summary of the key points about shells:

  • Provides Access: Shells offer a way to access the functionalities of the operating system.

  • Accepts Commands: Users can type commands to instruct the operating system to perform specific tasks.

  • Provides Feedback: The shell displays the output or results of the executed commands.

  • Two Types: Command-line shells (CLS) offer a more direct and powerful way to interact with the system, while graphical shells (GUI shells) provide a more user-friendly visual experience.

While GUI shells are dominant for everyday tasks, CLS (like Bash) can be much more efficient for repetitive tasks, automation, and scripting.

This lecture is focused on the widely used Bourne Again SHell (Bash).

Using the Shell

  • Open a terminal to access the shell prompt (e.g., missing:~$).

  • Type commands at the prompt to execute programs.

  • Example: date prints the current date and time.

  • Commands can take arguments (e.g., echo hello prints "hello").

  • The shell searches for programs in directories listed in the $PATH environment variable.

  • Use which to find the location of a program.

Navigating in the Shell

  • Paths specify locations of files and directories.

  • / is the root directory.

  • pwd shows the current working directory.

  • cd changes the current working directory.

  • ls lists the contents of a directory.

  • ls -l provides detailed information about files and directories.

  • Permissions (read, write, execute) control access to files and directories.

Connecting Programs

  • Programs have input and output streams (usually the keyboard and screen).

  • Redirection allows you to change these streams.

  • > redirects output to a file (e.g., echo hello > hello.txt).

  • < redirects input from a file (e.g., cat < hello.txt).

  • >> appends output to a file.

  • Pipes (|) connect the output of one program to the input of another (e.g., ls -l / | tail -n1).

A Versatile Tool

  • The sudo command allows you to run commands with root privileges (carefully!).

  • The /sys file system exposes kernel parameters for configuration (not on Windows or macOS).

Let's dive into some basic scripting...

Comments:

  • Lines starting with # are comments and ignored during script execution. They explain the purpose of the code block below them.

Shell Script Header (Shebang Line):

#!/usr/bin/bash

Variable Usage:

# Uppercase by convention
# Letters, numbers, underscores
NAME="Epsit"
echo "Hello ${NAME} 'sup?"
  • Variables store values that can be used throughout the script.

  • Variable names are typically uppercase by convention (though not strictly required).

  • They can contain letters, numbers, and underscores.

  • Assignment uses = to assign a value to a variable (e.g., NAME="Epsit").

  • Accessing a variable's value is done using $ followed by the variable name (e.g., $NAME).

  • String interpolation using ${NAME} within double quotes allows embedding variable values into strings (e.g., "Hello ${NAME} 'sup?").

User Input:

read -p "Enter your name: " NAME
echo "Hello $NAME, nice to meet you!"
  • The read command allows the script to prompt the user for input.

  • -p "Enter your name: " sets a prompt displayed before user input.

  • The user's input is stored in the variable specified after read (here, NAME).

Conditional Statements:

  • These control the script's flow based on certain conditions.

Simple if Statement:

if [ "$NAME" == "Epsit" ]
then
  echo "Wassup Epsit?"
fi
  • The if statement checks if a condition is true.

  • [ "$NAME" == "Epsit" ] compares the value of $NAME with "Epsit" using double square brackets [] for comparison.

  • == checks for equality.

  • The indented code block (echo "Wassup Epsit?") executes only if the condition is true.

if-else Statement:

if [ "$NAME" == "Epsit" ]
then
  echo "Wassup Epsit?"
else
  echo "You ain't Epsit"
fi
  • The else clause provides an alternative code block to execute if the if condition is false.

else-if (elif) Statement:

if [ "$NAME" == "Epsit" ]
then
  echo "Wassup Epsit?"
elif [ "$NAME" == "John Doe" ]
then
  echo "Ohhkay you are John Doe, a friend of Epsit."
else
  echo "You are some stranger for me, nothing else"
fi
  • The elif (else if) clause allows checking additional conditions if the initial if fails.

  • Multiple elif statements can be chained to handle various scenarios.

Comparison Operators:

NUM1=3
NUM2=5
if [ "$NUM1" -gt "$NUM2" ]
then
  echo "$NUM1 is greater than $NUM2"
else
  echo "$NUM1 is less than $NUM2"
fi
  • Comparison operators like -gt (greater than), -lt (less than), -eq (equal to), etc., are used within square brackets for numeric comparisons.

File Conditions:

# -f file  True if file is a regular file
# -e file  True if file exists (regardless of type)
# -d file  True if file is a directory
# -x file  True if the file is executable
# -w file  True if the file is writable
# -u file  True if the user id is set on a file
  • These operators check file properties within square brackets.

  • The example using -f "$FILE" checks if the file $FILE exists and is a regular file.

Looping:

total_lines=-1
FILE="hello.txt"
for file in "$FILE"
do
  lines=$(wc -l < "$FILE")
  total_lines=$((total_lines + lines))
done

echo "Total lines: $total_lines"

This code snippet demonstrates a loop in Bash scripting that calculates the total number of lines in a file. Here's a breakdown of its functionality:

Variable Initialization:

  • total_lines=-1: Initializes a variable total_lines to -1. This variable will store the accumulated total line count.

  • FILE="hello.txt": Initializes a variable FILE with the name of the file to be processed ("hello.txt" in this case).

for Loop:

  • for file in "$FILE": This line defines the loop structure.

    • for: Keyword indicating a loop.

    • file: This is a loop variable that will take on the value of each item in the list during each iteration.

    • in "$FILE": Specifies the list to iterate over. Here, it's just the single filename stored in the FILE variable (enclosed in double quotes).

Loop Body:

  • The indented code block (lines=$(wc -l < "$FILE"), total_lines=$((total_lines + lines))) executes for each item (filename) in the list.

    • lines=$(wc -l < "$FILE"):

      • This line counts the number of lines in the file and stores the result in the lines variable.

      • wc -l: The wc command with the -l flag counts the number of lines in a file.

      • < "$FILE": This redirects the output of wc -l (which is normally sent to the console) to the command following <, effectively treating the file content as input for wc -l.

    • total_lines=$((total_lines + lines)):

      • This line accumulates the line count from each iteration.

      • $(( )): This is a Bash arithmetic expansion construct. It performs mathematical operations on integers within double parentheses.

      • total_lines + lines: Adds the current line count (lines) to the previously accumulated total (total_lines).

Printing the Result:

  • echo "Total lines: $total_lines": After the loop finishes iterating through all items (the file list in this case), this line prints the final accumulated total line count stored in the total_lines variable.

And with this concludes my learnings of Shell Scripting: Day #1 (Though I also made some small shell scripting projects but I'll keep them in extras alongwith the solved exercises for this lecture, they'll be posted as separate blog discussion)... Let's stay tuned and see where the journey takes us. Signing off for now until my next blog comes.

Bleed code!