CS253: Software Development with C++

Spring 2023

Bash

Bash Lab                

Introduction                

For this lab, you will take a small bash script called rn, modify it to do more things, and turn it in for credit. A video introduction is available.                 

A script                

A bash script (or more generally, a shell script) is a series of bash commands in a file. You create the file using an editor, such as vim or nano, and then you execute (or run) the script, as if it were a program, because it is one.                 

Really, that’s all there is to it. Anything that you could type into an interactive bash shell (cd, ls, pwd, cp, mkdir, rm, make, vim, etc.), you can put into a bash script.                 

Also, bash scripts often contain other constructs more often found in programming languages, such as if, while, and for statements, and variable usage. You could use such things interactively, but you rarely do.                 

Basic bash programming                

     
if (( $# == 0 ))
then
    echo "I have no arguments. ☹"
fi
I have no arguments. ☹
    
echo Wildcard: /etc/host*
echo "Quotes protect it: /etc/host*"
Wildcard: /etc/host.conf /etc/hostname /etc/hosts
Quotes protect it: /etc/host*
    
echo "I am $USER"
I am cs253
    
echo 'Cost: $0.24'
Cost: $0.24
    
alpha="foo bar"
echo "I say $alpha"
I say foo bar
    
now=$(date)
echo "Current time: $now"
Current time: Thu Nov 21 09:31:17 MST 2024
    
let beta=2+2
echo "beta is $beta"
beta is 4
    if condition
    then
        statements
    fi

    
if [[ -e /etc/hostname ]]   # Does the file exist?
then
    cat /etc/hostname       # Let’s see it!
fi
beethoven
    if condition
    then
        statements
    else
        statements
    fi
    if condition
    then
        statements
    elif different-condition
    then
        statements
    else
        statements
    fi
    while condition
    do
        statements
    done
    for variable in list
    do
        statements
    done
    
for person in John Paul George Ringo
do
    echo $person was a Beatle.
done
John was a Beatle.
Paul was a Beatle.
George was a Beatle.
Ringo was a Beatle.
    
for file in /etc/*-release
do
    echo -n "Lines in $file: "
    wc -l <$file
done
Lines in /etc/almalinux-release: 1
Lines in /etc/centos-release: 1
Lines in /etc/os-release: 19
Lines in /etc/redhat-release: 1
Lines in /etc/system-release: 1
    
let age=2024-1957 money=20
if (( age >= 21 && money > 4 ))
then
    echo "You can buy a beer!"
fi
You can buy a beer!
    while [[ $suffix = "txt" ]]
    do
        somehow change the suffix
    done
    
ls -l /bin/sync /etc/hostname /etc/shadow
# Is this an executable file?
if [[ -x /bin/sync ]]
then
    echo /bin/sync is executable
fi
if [[ -e /etc/hostname ]]
then
    echo /etc/hostname exists
fi
if [[ -r /etc/shadow ]]
then
    echo /etc/shadow is readable
fi
-rwxr-xr-x  1 root root 38328 Apr  1  2023 /bin/sync
-rw-r--r--. 1 root root    10 Jan  5  2022 /etc/hostname
----------  1 root root  1880 Nov 30  2022 /etc/shadow
/bin/sync is executable
/etc/hostname exists
    
if grep -x -q selfie /usr/share/dict/words
then
    echo Dictionary is modern!
else
    echo Stupid stone-age dictionary.
fi
Stupid stone-age dictionary.

Script                

Here is a small bash script. It changes file suffixes:                 

#! /bin/bash

old_suffix=$1
new_suffix=$2

for f in *.$old_suffix
do
    new_name=${f%.*}.$new_suffix
    echo Rename $f to $new_name
done

You might use it like this, to rename all of your C files (ending in .c) to be C++ files (ending in .cpp):                 

    chmod +x rn
    ./rn c cpp

The chmod command makes the script executable, so we can treat it as a program. You only need to do that once.                 

The leading ./ in ./rn means that we want to execute the file rn that’s in the current directory, not some other file named rn somewhere else. For example, if you had a script called date, and foolishly just typed date, it might execute the official system command named date. You need ./date to make sure which date you’re running.                 

Copy the script, above, to the file rn. No suffix—just the two-character filename rn with nothing after. You will modify rn, and turn it in for credit.                 

For this lab, you should:                 

  1. Understand how the script works. You don’t have to write any of these down, you just have to do them. All that you turn in is the modified file rn.
  2. Understand why we type ./rn to run the script, as opposed to just typing rn.
  3. Copy & paste what I gave you into your own file rn, and try it out.
    Make sure that the first two characters in the script are #!, with nothing before them.
  4. Make it actually rename the file, rather than just saying so.
  5. Add a usage message if too many or too few arguments are given.
    A usage message is a message that tells the user what arguments to give to this script, if an improper number of arguments (including none) are given.
  6. Send the usage message to standard error.
  7. Complain (to standard error) and stop the script if a file can’t be renamed.
  8. Not clobber existing files. That is, if we run the script like this:
        ./rn foo bar
and both alpha.foo and alpha.bar exist, the script should complain and refuse to do anything else.

For extra fame & glory (but no extra points), you could:                 

  1. Add a -n option that doesn’t rename, but just says what it would do.
  2. Add a -v option that renames verbosely.
  3. Complain if no files have the given suffix.
  4. Make it work for filenames and suffixes that contain spaces.
  5. Make it work for suffixes that are wildcards (whatever that means).

How to submit your work:                

In Canvas, check in the file rn to the assignment “Lab02”. It’s due 11:59ᴘᴍ MT Saturday, with a 24-hour late period for a 25% penalty.                 

How to receive negative points:                

Turn in someone else’s work.