Day 2 Review

Commands from last week:

  • mkdir, rm -r — create/delete directories (avoid spaces in names)
  • nano — text editor; Ctrl+O saves, Ctrl+X exits
  • mv, cp — move and copy files
  • echo "text" > file.txt — create file; >> appends
  • * (any chars), ? (one char) — wildcard patterns
  • wc, sort, cut, uniq — counting, sorting, extracting columns
  • | chains commands; > saves output to file
Key concept

Commands are building blocks. Combine them with pipes to create powerful workflows.

Part 1: For Loops Demo

Navigate to exercise-data/creatures/ — you'll find three files: basilisk.dat, minotaur.dat, unicorn.dat.

The Problem: Repeating a Command

bash
$ head -n 5 basilisk.dat minotaur.dat unicorn.dat
# Works, but what if you had 100 files?

$ head -n 5 *.dat       # wildcard helps, but...

# What if you wanted only the CLASSIFICATION line from each?
$ head -n 2 basilisk.dat minotaur.dat unicorn.dat | tail -n 1
# Oops — only gets unicorn! This is why we need loops.

Your First Loop

bash
# Multi-line version (easier to read)
$ for filename in *.dat
> do
>   echo $filename
>   head -n 2 $filename | tail -n 1
> done

# One-line version (same thing)
$ for filename in *.dat; do echo $filename; head -n 2 $filename | tail -n 1; done
Semicolon placement

In one-line loops: semicolons go after the list, between commands inside the loop, and before done. If you forget, type the multi-line version first, then press the up arrow — the shell shows you the one-liner with semicolons already in place.

$ and > have two meanings

When the shell prints > or $, it's waiting for your input (a prompt). When you type them, you're redirecting output or getting a variable's value. Context matters.

Brace Expansion and Challenges

Brace Expansion

Instead of listing values one by one, use {} to generate sequences automatically.

bash
# Frustrating way — list every number
for loop_variable in 0 1 2 3 4 5 6 7 8 9; do echo $loop_variable; done

# Better way — brace expansion
for loop_variable in {0..9}; do echo $loop_variable; done

# More brace expansion examples
for i in {1..10}; do mkdir experiment_$i; done
for i in {10..1}; do echo $i; sleep 1; done; echo "Blastoff!"

Loop Challenges

Navigate to exercise-data/alkanes — six *.pdb files. Predict the output:

bash
# Challenge 1: what does this print, and why?
for datafile in *.pdb; do ls *.pdb; done

# Challenge 2: fix it to list each file once
for datafile in *.pdb; do ls $datafile; done

# Wildcard position matters
for filename in c*; do ls $filename; done     # starts with c
for filename in *c*; do ls $filename; done    # c anywhere in name

Saving Output in a Loop

bash
# > overwrites on each iteration (bad)
for alkanes in *.pdb; do cat $alkanes > alkanes.pdb; done

# >> appends — this is what you want
for datafile in *.pdb; do cat $datafile >> all.pdb; done

Nested Loops Challenge

bash
# Create a directory structure for experiments
for species in cubane ethane methane
do
  for temperature in 25 30 37 40
  do
    mkdir $species-$temperature
  done
done

# Add a script file to each temperature directory
for species in octane pentane propane
do
  mkdir $species
  for temperature in 25 30 37 40
  do
    mkdir $species/$temperature
    touch $species/$temperature/experiment.sh
  done
done
Part 2: Shell Scripts Demo

Navigate to exercise-data/alkanes. Shell scripts let you save a sequence of commands and run them again later.

Writing Your First Script

bash
$ nano middle.sh

Type the following into nano, save with Ctrl+O, exit with Ctrl+X:

bash
#!/bin/bash
head -n 15 octane.pdb | tail -n 5
bash
$ ls -lh middle.sh    # note permissions: rw-r--r-- (not executable)
$ chmod +x middle.sh  # make it executable
$ ls -lh middle.sh    # now shows rwxr-xr-x
$ ./middle.sh         # run it

Script Arguments: $1, $2, $3, $@

Hard-coding filenames is inflexible. Use variables to accept arguments from the command line.

bash
# Edit middle.sh to use $1 (first argument)
head -n 15 "$1" | tail -n 5

$ ./middle.sh octane.pdb

# Edit again to use all three arguments
head -n "$2" "$1" | tail -n "$3"

$ bash middle.sh pentane.pdb 15 5
$ bash middle.sh pentane.pdb 20 5

Adding Comments

Comments (lines starting with #) explain what a script does. Always include them.

bash
# select lines from the middle of a file
# usage: bash middle.sh filename end_line num_lines

head -n "$2" "$1" | tail -n "$3"

The $@ Variable — All Arguments

bash
$ nano sorted.sh
bash
# sort files by their length
# usage: bash sorted.sh one_or_more_filenames

wc -l "$@" | sort -n
bash
$ bash sorted.sh *.pdb ../creatures/*.dat
AI Centerpiece: Write a Shell Script AI

Now it's your turn. Instead of writing this script from scratch, describe what you want to AI and let it write the code — then read it, understand it, and run it.

Try this prompt in Claude or ChatGPT
I'm learning bash scripting. Please write a shell script called experiment_setup.sh that does the following: 1. Has a shebang line (#!/bin/bash) and comments explaining what it does 2. Creates a log file called setup_log.txt 3. Writes "Experiment setup started: [current date/time]" to the log file 4. Uses a nested loop to create directories for three species (cubane, ethane, methane) and four temperatures (25, 30, 37, 40) 5. Inside each temperature directory, creates an empty file called experiment.sh 6. Logs each directory it creates to the log file 7. Writes "Setup completed: [current date/time]" to the log at the end 8. Prints a message to the screen when it finishes Please explain what each part of the script does.

Once you have the script from AI, save it as experiment_setup.sh, make it executable with chmod +x experiment_setup.sh, and run it with ./experiment_setup.sh. Check the output and the log file.

The complete script (reference)

Here is what the finished script should look like. Compare it to what AI generated for you.

bash
#!/bin/bash
# script to set up experimental directory structure

log_file="setup_log.txt"

echo "Experiment setup started: $(date)" > $log_file

for species in cubane ethane methane
do
    mkdir $species
    echo "Created $species directory" >> $log_file

    for temperature in 25 30 37 40
    do
        mkdir $species/$temperature
        touch $species/$temperature/experiment.sh
        echo "  - Created $species/$temperature/" >> $log_file
    done
done

echo "Setup completed: $(date)" >> $log_file
echo "Setup complete! Check $log_file for details."
Before Day 4

Create a free GitHub account if you don't have one. We'll use it on Day 4 for remote repositories.