Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
34 views34 pages

Command Line Interface and Scripting SGA2

The document contains a series of Bash scripts designed for various tasks including managing fruit prices, a to-do list, student records, email validation, file management, and text processing. Each script includes functions for specific operations such as adding, deleting, and displaying records or files, as well as validating inputs. The scripts are structured to handle user input and provide feedback based on the operations performed.

Uploaded by

jaroliaprateek
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views34 pages

Command Line Interface and Scripting SGA2

The document contains a series of Bash scripts designed for various tasks including managing fruit prices, a to-do list, student records, email validation, file management, and text processing. Each script includes functions for specific operations such as adding, deleting, and displaying records or files, as well as validating inputs. The scripts are structured to handle user input and provide feedback based on the operations performed.

Uploaded by

jaroliaprateek
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Command Line Interfaces and Scripting

Staff Graded Assignment-2


By Sarthak Maji

Question 1:

#!/bin/bash

if [[ $# -eq 0 ]]; then


while read -r line; do
fruit=$(echo $line | awk '{print $1}')
price=$(echo $line | awk '{print $3}')
quantity=$(echo $line | awk '{print $4}')
total_price=$((price * quantity))
echo "$fruit $total_price"
done < fruits.txt
elif [[ $# -eq 1 ]]; then
if [[ $1 =~ ^[A-Za-z]$ ]]; then
grep " $1 " fruits.txt | awk '{total+=$3*$4; print $1;
fruit_prices+=$3*$4} END {print total}'
elif [[ $1 =~ ^[0-9]+$ ]]; then
awk -v limit=$1 '$3 <= limit {print $1}' fruits.txt
else
grep -i "^$1 " fruits.txt | awk '{print $2, $3}'
fi
else
echo "Error: Invalid number of arguments"
fi

Output:

2023EB03175 2023EB03175
Question 2

#!/bin/bash

TODO_FILE="todo.txt"

# Ensure the todo file exists


touch $TODO_FILE

# Function to display all tasks


display_tasks() {
if [ ! -s "$TODO_FILE" ]; then
echo "No tasks found."
return
fi
cat -n "$TODO_FILE"
}

# Function to display tasks based on status


display_tasks_by_status() {
local status=$1
local status_name
case "$status" in
0) status_name="TODO";;
1) status_name="DOING";;
2) status_name="COMPLETED";;
esac

if [ ! -s "$TODO_FILE" ]; then
echo "No tasks found."
return
fi

echo "$status_name tasks:"


grep " $status\$" "$TODO_FILE" | while read -r line; do
echo "$line"
done
}

# Function to add a new task


add_task() {
if [ -z "$1" ]; then
echo "Error: Task description required"
return 1
fi
local task="$1"
local serial_number=$(($(wc -l < "$TODO_FILE") + 1))
printf "%d %s %d\n" "$serial_number" "$task" 0 >>
"$TODO_FILE"
echo "Task added: $task"
}

# Function to mark tasks as complete


mark_complete() {
if [ $# -eq 0 ]; then
echo "Error: Please provide task number(s) to mark as
complete"
return 1
fi
for serial in "$@"; do
if ! [[ "$serial" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid task number: $serial"
continue
fi
sed -i "${serial}s/ [012]$/ 2/" "$TODO_FILE"
done
echo "Marked tasks as complete: $@"
}

# Function to delete tasks


delete_tasks() {
for serial in "$@"; do
sed -i "${serial}d" $TODO_FILE
done
echo "Deleted tasks: $@"
}

# Main script logic


case "$1" in
"")
display_tasks_by_status 0
;;
"display")
display_tasks
;;
"add")
shift
add_task "$*"
;;
"todo")
display_tasks_by_status 0
;;
"doing")
display_tasks_by_status 1
;;
"complete")
display_tasks_by_status 2
;;
"mark_complete")
shift
mark_complete "$@"
;;
"delete")
shift
delete_tasks "$@"
;;
*)
echo "Error: Invalid command"
;;
esac

Output:
2023EB03175
2023EB03175

2023EB03175
2023EB03175

2023EB03175

2023EB03175

2023EB03175
Question 3:

#!/bin/bash

DATA_FILE="data.txt"

# Ensure the data file exists


touch "$DATA_FILE"

# Function to validate roll number (4 digits)


validate_roll() {
if [[ ! "$1" =~ ^[0-9]{4}$ ]]; then
return 1
fi
# Check if roll number already exists
if grep -q "^$1 " "$DATA_FILE"; then
return 1
fi
return 0
}

# Function to validate marks (0-100)


validate_marks() {
if [[ ! "$1" =~ ^[0-9]+$ ]] || [ "$1" -lt 0 ] || [ "$1" -gt
100 ]; then
return 1
fi
return 0
}

# Function to add student record


add_student() {
local roll name history geography civics

while true; do
read -p "Enter Roll Number (4 digits): " roll
if validate_roll "$roll"; then
break
fi
echo "Invalid roll number or roll number already exists.
Please try again."
done

read -p "Enter Name: " name

while true; do
read -p "Enter History Marks (0-100): " history
if validate_marks "$history"; then
break
fi
echo "Invalid marks. Please enter a number between 0 and
100."
done

while true; do
read -p "Enter Geography Marks (0-100): " geography
if validate_marks "$geography"; then
break
fi
echo "Invalid marks. Please enter a number between 0 and
100."
done

while true; do
read -p "Enter Civics Marks (0-100): " civics
if validate_marks "$civics"; then
break
fi
echo "Invalid marks. Please enter a number between 0 and
100."
done

echo "$roll $name $history $geography $civics" >>


"$DATA_FILE"
echo "Record added successfully!"
}

# Function to print passing students


print_passing_students() {
echo "List of Passing Students (>=33 in each subject):"
echo "Roll Name History Geography Civics"
echo "----------------------------------------"
while read -r line; do
read -r roll name history geography civics <<< "$line"
if [ "$history" -ge 33 ] && [ "$geography" -ge 33 ] && [
"$civics" -ge 33 ]; then
printf "%-6s %-6s %-8d %-9d %d\n" "$roll" "$name"
"$history" "$geography" "$civics"
fi
done < "$DATA_FILE"
}

# Function to calculate and print divisions


print_divisions() {
echo "Student Divisions:"
echo "Roll Name Average Division"
echo "--------------------------------"
while read -r line; do
read -r roll name history geography civics <<< "$line"
average=$(( (history + geography + civics) / 3 ))

if [ "$history" -lt 33 ] || [ "$geography" -lt 33 ] || [


"$civics" -lt 33 ]; then
division="Fail"
elif [ "$average" -ge 75 ]; then
division="First"
elif [ "$average" -ge 60 ]; then
division="Second"
else
division="Third"
fi

printf "%-6s %-6s %-9d %s\n" "$roll" "$name" "$average"


"$division"
done < "$DATA_FILE"
}

# Function to delete student record


delete_student() {
local roll
read -p "Enter Roll Number to delete: " roll
if grep -q "^$roll " "$DATA_FILE"; then
sed -i "/^$roll /d" "$DATA_FILE"
echo "Record deleted successfully!"
else
echo "Roll number not found!"
fi
}

# Main menu loop


while true; do
echo -e "\nStudent Record Management System"
echo "1. Add a student record"
echo "2. Print list of passing students"
echo "3. Print list of students with divisions"
echo "4. Delete a student record"
echo "5. Exit"
read -p "Enter your choice (1-5): " choice

case $choice in
1) add_student ;;
2) print_passing_students ;;
3) print_divisions ;;
4) delete_student ;;
5) echo "Goodbye!"; exit 0 ;;
*) echo "Invalid choice. Please enter a number between 1
and 5." ;;
esac
done

Output:

2023EB03175
2023EB03175
2023EB03175
Question 4
#!/bin/bash

EMAIL_FILE="emails.txt"
VALID_EMAIL_FILE="valid_emails.txt"

# Ensure the email file exists


touch "$EMAIL_FILE"

# Function to validate email format


validate_email() {
local email=$1
if [[ $email =~ ^[A-Za-z0-9]+@[A-Za-z]+\.com$ ]]; then
return 0
fi
return 1
}

# Function to add email


add_email() {
local email
read -p "Enter email address: " email

if validate_email "$email"; then


echo "$email" >> "$EMAIL_FILE"
echo "Email added successfully!"
else
echo "Invalid email format! Email should be in format:
letters/[email protected]"
fi
}

# Function to get valid emails


get_valid_emails() {
echo "Checking for valid emails..."
# Clear the valid emails file
> "$VALID_EMAIL_FILE"

while IFS= read -r email || [ -n "$email" ]; do


if validate_email "$email"; then
echo "$email" >> "$VALID_EMAIL_FILE"
fi
done < "$EMAIL_FILE"

if [ -s "$VALID_EMAIL_FILE" ]; then
echo "Valid emails have been saved to $VALID_EMAIL_FILE"
echo "Valid emails:"
cat "$VALID_EMAIL_FILE"
else
echo "No valid emails found!"
fi
}

# Main menu loop


while true; do
echo -e "\nEmail Management System"
echo "1. Add email"
echo "2. Get valid emails"
echo "3. Exit"
read -p "Enter your choice (1-3): " choice

case $choice in
1) add_email ;;
2) get_valid_emails ;;
3) echo "Goodbye!"; exit 0 ;;
*) echo "Invalid choice. Please enter a number between 1
and 3." ;;
esac
done

Output:

2023EB03175
2023EB03175

Question 5

#!/bin/bash

SOURCE_DIR="source"
DEST_DIR="destination"

# Ensure both directories exist


if [ ! -d "$SOURCE_DIR" ] || [ ! -d "$DEST_DIR" ]; then
echo "Error: source and destination directories must exist"
exit 1
fi

# Function to compare files and print identical ones


compare_files() {
echo "Identical files in source and destination:"
local found=0

for src_file in "$SOURCE_DIR"/*; do


if [ ! -f "$src_file" ]; then continue; fi

filename=$(basename "$src_file")
dest_file="$DEST_DIR/$filename"

if [ -f "$dest_file" ] && cmp -s "$src_file"


"$dest_file"; then
echo "$filename"
found=1
fi
done

if [ $found -eq 0 ]; then


echo "No identical files found"
fi
}

# Function to copy non-identical files


copy_files() {
local extension="$1"
local copied=0

for src_file in "$SOURCE_DIR"/*; do


if [ ! -f "$src_file" ]; then continue; fi

filename=$(basename "$src_file")
dest_file="$DEST_DIR/$filename"

# If extension is specified, check if file matches


if [ -n "$extension" ]; then
if [[ "$filename" != *".$extension" ]]; then
continue
fi
fi

# Copy only if files are different or destination


doesn't exist
if [ ! -f "$dest_file" ] || ! cmp -s "$src_file"
"$dest_file"; then
cp "$src_file" "$dest_file"
echo "Copied: $filename"
copied=1
fi
done

if [ $copied -eq 0 ]; then


echo "No files copied"
fi
}

# Function to move all files


move_files() {
local moved=0

for src_file in "$SOURCE_DIR"/*; do


if [ ! -f "$src_file" ]; then continue; fi
filename=$(basename "$src_file")
mv "$src_file" "$DEST_DIR/"
echo "Moved: $filename"
moved=1
done

if [ $moved -eq 0 ]; then


echo "No files moved"
fi
}

# Function to perform backup operation


backup_files() {
echo "Performing backup..."

# Copy unique files from source to destination


for src_file in "$SOURCE_DIR"/*; do
if [ ! -f "$src_file" ]; then continue; fi

filename=$(basename "$src_file")
dest_file="$DEST_DIR/$filename"

if [ ! -f "$dest_file" ]; then
cp "$src_file" "$dest_file"
echo "Copied to destination: $filename"
elif ! cmp -s "$src_file" "$dest_file"; then
cp "$src_file" "$dest_file"
echo "Updated in destination: $filename"
fi
done

# Copy unique files from destination to source


for dest_file in "$DEST_DIR"/*; do
if [ ! -f "$dest_file" ]; then continue; fi

filename=$(basename "$dest_file")
src_file="$SOURCE_DIR/$filename"

if [ ! -f "$src_file" ]; then
cp "$dest_file" "$src_file"
echo "Copied to source: $filename"
fi
done
}

# Main script logic


case "$1" in
"")
compare_files
;;
"copy")
if [ -n "$2" ]; then
copy_files "$2"
else
copy_files
fi
;;
"move")
move_files
;;
"backup")
backup_files
;;
*)
echo "Invalid command"
echo "Usage:"
echo "./compare.sh - List identical files"
echo "./compare.sh copy - Copy non-identical files
from source to destination"
echo "./compare.sh copy ext - Copy files with specific
extension"
echo "./compare.sh move - Move all files from
source to destination"
echo "./compare.sh backup - Sync both directories"
;;
esac
Output:

2023EB03175
2023EB03175

Question 6:
#!/bin/bash

FILE="paragraph.txt"

# Check if file exists


if [ ! -f "$FILE" ]; then
echo "Error: $FILE does not exist"
exit 1
fi

# Function to count words


count_words() {
local count=$(wc -w < "$FILE")
echo "Number of words: $count"
}

# Function to count lines


count_lines() {
local count=$(wc -l < "$FILE")
echo "Number of lines: $count"
}

# Function to lookup word occurrences


lookup_word() {
local text="$1"
if [ -z "$text" ]; then
echo "Error: Please provide text to lookup"
return 1
fi

local count=$(grep -wo "$text" "$FILE" | wc -l)


echo "Occurrences of '$text': $count"
}

# Function to replace text


replace_text() {
local text1="$1"
local text2="$2"

if [ -z "$text1" ] || [ -z "$text2" ]; then


echo "Error: Please provide both text to replace and
replacement text"
return 1
fi

# Create backup of original file


cp "$FILE" "${FILE}.bak"

# Perform replacement
sed -i "s/\b${text1}\b/${text2}/g" "$FILE"

local count=$(grep -wo "$text2" "$FILE" | wc -l)


echo "Replaced '$text1' with '$text2'"
echo "Number of replacements: $count"
}

# Main script logic


case "$1" in
"words")
count_words
;;
"lines")
count_lines
;;
"lookup")
lookup_word "$2"
;;
"replace")
replace_text "$2" "$3"
;;
*)
echo "Usage:"
echo "./strings.sh words - Count
words"
echo "./strings.sh lines - Count
lines"
echo "./strings.sh lookup <text> - Count
occurrences of <text>"
echo "./strings.sh replace <text1> <text2> - Replace
<text1> with <text2>"
;;
esac

Output:

2023EB03175
Question7:
#!/bin/bash

INPUT_FILE="paragraph.txt"
BEGINNING_FILE="beginning.txt"
ENDING_FILE="ending.txt"

# Check if input file exists


if [ ! -f "$INPUT_FILE" ]; then
echo "Error: $INPUT_FILE does not exist"
exit 1
fi

# Clear or create output files


> "$BEGINNING_FILE"
> "$ENDING_FILE"

# Function to find words beginning with vowels


find_vowel_beginnings() {
echo "Finding words beginning with vowels..."
grep -oE '\b[aeiouAEIOU][a-zA-Z]*\b' "$INPUT_FILE" | sort -u
> "$BEGINNING_FILE"
echo "Words beginning with vowels saved to $BEGINNING_FILE"
}

# Function to find words ending with vowels


find_vowel_endings() {
echo "Finding words ending with vowels..."
grep -oE '\b[a-zA-Z]*[aeiouAEIOU]\b' "$INPUT_FILE" | sort -u
> "$ENDING_FILE"
echo "Words ending with vowels saved to $ENDING_FILE"
}

# Function to find words beginning and ending with same letter


find_same_letter_words() {
echo -e "\nWords beginning and ending with the same letter:"
echo "------------------------------------------------"

# Extract words and convert to lowercase for comparison


grep -oE '\b[a-zA-Z]+\b' "$INPUT_FILE" | while read -r word;
do
first_letter=$(echo "${word:0:1}" | tr '[:upper:]'
'[:lower:]')
last_letter=$(echo "${word: -1}" | tr '[:upper:]'
'[:lower:]')
if [ "$first_letter" = "$last_letter" ]; then
echo "$word"
fi
done
}

# Execute all functions


find_vowel_beginnings
find_vowel_endings
find_same_letter_words

# Print summary
echo -e "\nSummary:"
echo "Number of words beginning with vowels: $(wc -l <
"$BEGINNING_FILE")"
echo "Number of words ending with vowels: $(wc -l <
"$ENDING_FILE")"

Output:

2023EB03175
Question 8:
#!/bin/bash

# Function to check if directory exists


check_directory() {
if [ ! -d "$1" ]; then
echo "Error: Directory '$1' does not exist"
exit 1
fi
}

# Function to get file extension


get_extension() {
local filename="$1"
if [[ "$filename" == *.* ]]; then
echo "${filename##*.}"
fi
}

# Function to move file using a child process


move_file() {
local file="$1"
local ext="$2"
local dir_path="$3"

# Create target directory if it doesn't exist


local target_dir="${dir_path}/${ext}_files"
mkdir -p "$target_dir"

# Move file in a child process


(
if mv "$file" "$target_dir/"; then
echo "Moved: $(basename "$file") -> ${ext}_files/"
else
echo "Failed to move: $file"
fi
) &
}

# Main script
echo "Enter directory path:"
read -r dir_path

# Remove trailing slash if present


dir_path="${dir_path%/}"
# Validate directory
check_directory "$dir_path"

# Process files
echo "Processing files..."
for file in "$dir_path"/*; do
# Skip if not a file or is in a subdirectory
if [ ! -f "$file" ] || [ "$(dirname "$file")" != "$dir_path"
]; then
continue
fi

# Get file extension


ext=$(get_extension "$(basename "$file")")
if [ -n "$ext" ]; then
move_file "$file" "$ext" "$dir_path"
fi
done

# Wait for all child processes to complete


wait

echo -e "\nFile organization complete!"


echo "Summary of created directories:"
for dir in "$dir_path"/*_files/; do
if [ -d "$dir" ]; then
count=$(ls -1 "$dir" 2>/dev/null | wc -l)
dirname=$(basename "$dir")
echo "$dirname: $count files"
fi
done
Output:

2023EB03175

Question 9:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

// Signal handler for SIGCHLD


void handle_sigchld(int sig) {
int status;
pid_t pid;
// Wait for any child process that has terminated
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("Child process %d has been cleaned up\n", pid);
}
}

// Function to demonstrate zombie process


void create_zombie() {
pid_t zombie_pid = fork();

if (zombie_pid < 0) {
perror("Fork failed");
exit(1);
}

if (zombie_pid == 0) {
// Child process
printf("Zombie child process %d is running\n",
getpid());
exit(0); // Child terminates immediately
} else {
// Parent process
printf("Parent process %d created potential zombie
%d\n", getpid(), zombie_pid);
sleep(2); // Give time to observe process states
}
}

// Function to demonstrate orphan process


void create_orphan() {
pid_t orphan_pid = fork();

if (orphan_pid < 0) {
perror("Fork failed");
exit(1);
}

if (orphan_pid == 0) {
// Child process that will become orphan
printf("Child process %d is running (Parent: %d)\n",
getpid(), getppid());
sleep(2); // Wait for parent to terminate

printf("Child process %d is now orphaned (New Parent:


%d)\n",
getpid(), getppid());
sleep(1);
exit(0);
} else {
// Parent process
printf("Parent process %d created potential orphan
%d\n",
getpid(), orphan_pid);
sleep(1); // Give child time to print initial message
printf("Parent process %d is terminating\n", getpid());
exit(0); // Parent terminates, making child an orphan
}
}

int main() {
// Set up signal handler for SIGCHLD
struct sigaction sa;
sa.sa_handler = handle_sigchld;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;

if (sigaction(SIGCHLD, &sa, NULL) == -1) {


perror("sigaction");
exit(1);
}

printf("\nDemonstrating Zombie Process:\n");


printf("-----------------------------\n");
create_zombie();

printf("\nDemonstrating Orphan Process:\n");


printf("-----------------------------\n");
create_orphan();

return 0;
}
Output:

2023EB03175

Question 10:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

// Global variables to control printing


volatile sig_atomic_t print_red = 1;
volatile sig_atomic_t print_yellow = 0;
volatile sig_atomic_t print_green = 0;
volatile sig_atomic_t should_exit = 0;
pid_t parent_pid;

// Signal handler for SIGUSR1 (from first child)


void handle_sigusr1(int signum) {
print_red = 0;
print_yellow = 1;
}

// Signal handler for SIGUSR2 (from second child)


void handle_sigusr2(int signum) {
print_yellow = 0;
print_green = 1;
should_exit = 1;
}

// Signal handler for SIGINT (Ctrl+C)


void handle_sigint(int signum) {
printf("\nParent process ID: %d\n", parent_pid);
exit(0);
}

int main() {
pid_t child1_pid, child2_pid;
parent_pid = getpid();

// Set up signal handlers


signal(SIGUSR1, handle_sigusr1);
signal(SIGUSR2, handle_sigusr2);
signal(SIGINT, handle_sigint);

// Create first child


child1_pid = fork();
if (child1_pid < 0) {
perror("Fork failed for child 1");
exit(1);
}

if (child1_pid == 0) {
// First child process
sleep(5);
kill(parent_pid, SIGUSR1);
exit(0);
}

// Parent continues to create second child


child2_pid = fork();
if (child2_pid < 0) {
perror("Fork failed for child 2");
exit(1);
}

if (child2_pid == 0) {
// Second child process
sleep(10);
kill(parent_pid, SIGUSR2);
exit(0);
}

// Parent process
printf("Parent PID: %d\n", parent_pid);
printf("Child 1 PID: %d\n", child1_pid);
printf("Child 2 PID: %d\n", child2_pid);
printf("\nStarting traffic light simulation...\n\n");

// Keep running until should_exit is set and green is shown


while (1) {
if (print_red) {
printf("\033[1;31mred\033[0m\n");
} else if (print_yellow) {
printf("\033[1;33myellow\033[0m\n");
} else if (print_green) {
printf("\033[1;32mgreen\033[0m\n");
if (should_exit) {
break;
}
}
usleep(500000); // Sleep for 0.5 seconds
}

printf("\nTraffic light simulation completed.\n");


return 0;
}
Output:

2023EB03175

2023EB03175

Note*: Easy Syntax Highlighter has been used to make the code look organized.

You might also like