Link Search Menu Expand Document

Homework 01: Shell Tools and Scripting

Due to the length of this homework, we are only assigning 4 problems instead of the usual 5.

Homework Update

Run git pull to grab the latest homework.

Our autograder requires a new Python 3.7 feature. If the autograder is erroring on your machine, ensure that you have a recent version of Python.

MacOS Users Only: Setup

As many of you may know, MacOS and Linux have several differences. One such difference is the behavior of some command line tools. (If you’re curious, feel free to read this.) These differences are quite minor but cause issues with our autograder.

To fix this issue, we would like you to install GNU Coreutils so that you can use the utilities that would be found on a Linux systems. Please follow the instructions below:

  1. Install brew
  2. Install utilities: brew install coreutils ed findutils gawk gnu-sed gnu-tar grep make

After you do so, the GNU utilities will be accessible via g + the original command. (For example, GNU ls is usable via gls.) You can find a full list of commands installed here.

Required Questions

  1. Read man ls and write an ls command that lists files in the following manner

    • Includes all files, including hidden files
    • Sizes are listed in human readable format (e.g. 454M instead of 454279954)
    • Files are ordered by recency
    • Output is colorized

    A sample output would look like this

     -rw-r--r--   1 user group 1.1M Jan 14 09:53 baz
     drwxr-xr-x   5 user group  160 Jan 14 09:53 .
     -rw-r--r--   1 user group  514 Jan 14 06:42 bar
     -rw-r--r--   1 user group 106M Jan 13 12:12 foo
     drwx------+ 47 user group 1.5K Jan 12 18:08 ..
    

    MacOS Users: Please use gls instead of ls.

    Write this command in an executable file called myls.

  2. Write bash functions marco and polo that do the following. Whenever you execute marco the current working directory should be saved in some manner, then when you execute polo, no matter what directory you are in, polo should cd you back to the directory where you executed marco. Write these two functions in a file called marco.sh For ease of debugging, you can (re)load the definitions to your shell by executing source marco.sh.

  3. Say you have a command that fails rarely, as shown below with random.sh. In order to debug it you need to capture its output but it can be time consuming to get a failure run. Write a bash script that runs the following script until it fails and captures its standard output and error streams to out.txt and prints everything at the end. Bonus points if you can also report how many runs it took for the script to fail.

     #!/usr/bin/env bash
    
     n=$(( RANDOM % 100 ))
    
     if [[ n -eq 42 ]]; then
        echo "Something went wrong"
        >&2 echo "The error was using magic numbers"
        exit 1
     fi
    
     echo "Everything went according to plan"
    

    Save your script in a file called debug_failing_command.sh.

  4. As we covered in the lecture find’s -exec can be very powerful for performing operations over the files we are searching for. However, what if we want to do something with all the files, like creating a tar file (man tar)? As you have seen so far commands will take input from both arguments and STDIN. When piping commands, we are connecting STDOUT to STDIN, but some commands like tar take inputs from arguments. To bridge this disconnect there’s the xargs command which will execute a command using STDIN as arguments. For example ls | xargs rm will delete the files in the current directory.

    Your task is to write a command that recursively finds all HTML files in the folder and makes a tarball with them (like a zipfile). This tarred file should be called archive.tar.gz. Note that your command should work even if the files have spaces (hint: check -d flag for xargs).

    Save your script in a file called tar_html.sh.

    MacOS Users: Please use gfind instead of find, gxargs instead of xargs, and gtar instead of tar.

    Note: If you’re on macOS and you’d like to do this assignment again without using GNU utils, note that the default BSD find is different from the one included in GNU coreutils. You can use -print0 on find and the -0 flag on xargs. As a macOS user, you should be aware that command-line utilities shipped with macOS may differ from the GNU counterparts; you can install the GNU versions if you like by using brew.

    For Gradescope, please use the GNU utils.

Submit your work by uploading the files myls, marco.sh, debug_failing_command.sh, and tar_html.sh to the Gradescope assignment.

Optional Questions

  1. (Advanced) Write a command or script to recursively find the most recently modified file in a directory. More generally, can you list all files by recency?