BeamerReveal
view release on metacpan or search on metacpan
test/2026-02-04-DRM/the_shell.tex view on Meta::CPAN
$ cd ..
$ pwd
/home/user
\end{verbatim}
\end{exampleblock}
\end{column}
\end{columns}
\end{frame}
\begin{frame}[label={sec:org42c7d7e},fragile]{Think-Pair-Share: Navigation Puzzle}
\begin{block}{The Path}
You start in \texttt{/home/user/docs}. You run the following command:
\begin{verbatim}
cd .././photos/../././docs/../../
\end{verbatim}
\end{block}
\begin{exampleblock}{The Question}\label{sec:org030ec48}
Where are you now? Work with a partner to trace the path step-by-step.
\end{exampleblock}
\begin{alertblock}<2->{Answer}
\alert{/home}
\begin{enumerate}[<+->]
\item \texttt{..} \(\rightarrow\) \texttt{/home/user}
\item \texttt{./photos} \(\rightarrow\) \texttt{/home/user/photos}
\item \texttt{..} \(\rightarrow\) \texttt{/home/user}
\item \texttt{././docs} \(\rightarrow\) \texttt{/home/user/docs}
\item \texttt{../../} \(\rightarrow\) \texttt{/home}
\end{enumerate}
\end{alertblock}
\end{frame}
\begin{frame}[label={sec:orgfb7508b},fragile]{File and Directory Manipulation}
\begin{block}{Common Operations}
\begin{center}
\begin{tabular}{ll}
Command & Description\\
\hline
\texttt{mkdir <dir>} & Make directory\\
\texttt{touch <file>} & Create empty file / update timestamp\\
\texttt{cp <src> <dst>} & Copy files/directories\\
\texttt{mv <src> <dst>} & Move/rename files\\
\texttt{rm <file>} & Remove files\\
\end{tabular}
\end{center}
\end{block}
\begin{alertblock}<2->{What do these flags actually do?}
\begin{itemize}[<+->]
\item \alert{-r}: Recursive (directories)
\item \alert{-i}: Interactive (ask before delete)
\item \alert{-f}: Force (no prompt)
\item \alert{-v}: Verbose (show progress)
\end{itemize}
\end{alertblock}
\end{frame}
\begin{frame}[label={sec:org8fb515c},fragile]{File Manipulation Examples}
\begin{block}{Examples}
\begin{verbatim}
# Create nested directories
mkdir -p project/src/utils
# Copy a folder and all its contents
cp -r folder1 folder1_backup
# Rename a file
mv old_name.txt new_name.txt
# Remove a folder and its contents (be careful!)
rm -rf temporary_work
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:orgdc1b1a9},fragile]{Time to Explore: File Operations}
\begin{block}{Challenge}
Perform the following tasks using only the shell:
\begin{enumerate}
\item Create a directory named \texttt{STIC}, and inside it, a directory named \texttt{lab1}.
\item Create three empty files in \texttt{lab1} named \texttt{test1.py}, \texttt{test2.py}, and \texttt{notes.txt}.
\item Copy \texttt{notes.txt} to a new file called \texttt{README.md}.
\item Move all \texttt{.py} files into a new subdirectory called \texttt{src}.
\item Try to remove the \texttt{STIC} directory using \texttt{rmdir}. Why does it fail?
\end{enumerate}
\end{block}
\end{frame}
\begin{frame}<2->[label={sec:orgafc541d},fragile]{Solutions: File Operations}
\begin{exampleblock}{Steps}\label{sec:orgb76a3eb}
\begin{verbatim}
# 1. Create nested
mkdir -p STIC/lab1
# 2. Create files
touch STIC/lab1/test1.py STIC/lab1/test2.py STIC/lab1/notes.txt
# 3. Copy
cp STIC/lab1/notes.txt STIC/lab1/README.md
# 4. Move
mkdir STIC/lab1/src
mv STIC/lab1/*.py STIC/lab1/src/
# 5. Why fail?
rmdir STIC # Fails: "Directory not empty"
rm -r STIC # Use recursive remove instead!
\end{verbatim}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org7d70369},fragile]{Viewing File Contents}
\begin{block}{Why not just use VS Code?}
What if the file is on a remote server? What if it's 10GB?
\end{block}
\begin{block}<2->{Viewing Commands}
\begin{center}
\begin{tabular}{ll}
Command & Description\\
\hline
\texttt{cat <file>} & Display entire file\\
\texttt{less <file>} & Page through file (q to quit)\\
\texttt{head -n N <file>} & Show first N lines\\
\texttt{tail -n N <file>} & Show last N lines\\
\texttt{tail -f <file>} & Follow file updates (logs)\\
\end{tabular}
\end{center}
test/2026-02-04-DRM/the_shell.tex view on Meta::CPAN
\begin{block}{The Challenge}
You are working on a massive project. You need to find a "TODO" comment related to "authentication" in any file.
\alert{\alert{Task:}} How would you find this line using only \texttt{grep}? Discuss with your neighbor the flags you'd need.
\end{block}
\begin{alertblock}<2->{Possible Solution}
\begin{verbatim}
$ grep -rn "TODO.*authentication" .
\end{verbatim}
\begin{itemize}
\item \alert{-r}: Search all files in all subdirectories.
\item \alert{-n}: Tell me exactly which line the comment is on!
\end{itemize}
\end{alertblock}
\end{frame}
\begin{frame}[label={sec:org0eb0ee7},fragile]{Wildcards and Globbing}
\begin{block}{Glob Patterns}
\begin{center}
\begin{tabular}{ll}
Pattern & Matches\\
\hline
\texttt{*} & Any string (including empty)\\
\texttt{?} & Any single character\\
\texttt{[abc]} & Any character in brackets\\
\texttt{[a-z]} & Any character in range\\
\end{tabular}
\end{center}
\end{block}
\end{frame}
\begin{frame}[label={sec:org15d25dd},fragile]{Globbing Examples}
\begin{block}{Basic Wildcards}
\begin{verbatim}
# All .txt files
ls *.txt
# Files starting with 'test'
ls test*
# Single character: matches file1.txt but not file10.txt
ls file?.txt
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org7887512},fragile]{Globbing Examples - Advanced}
\begin{block}{Character Sets and Negation}
\begin{verbatim}
# Match specific numbers
ls file[123].txt
# Match any lowercase letter
ls [a-z]*.txt
# Negation: anything NOT starting with a-z
ls [!a-z]*
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org68bd5ca},fragile]{Time to Explore: Globbing}
\begin{block}{Files in Directory}
\texttt{img1.png}, \texttt{img10.png}, \texttt{img2.png}, \texttt{image.png}, \texttt{backup\_img1.png}
\end{block}
\begin{exampleblock}{Predict}\label{sec:org735de1c}
Which files match these patterns?
\begin{enumerate}
\item \texttt{img?.png}
\item \texttt{img*.png}
\item \texttt{img[1-9].png}
\item \texttt{*img1.png}
\end{enumerate}
\end{exampleblock}
\begin{alertblock}<2->{Answers}
\begin{enumerate}[<+->]
\item \texttt{img1.png}, \texttt{img2.png}
\item \texttt{img1.png}, \texttt{img10.png}, \texttt{img2.png}
\item \texttt{img1.png}, \texttt{img2.png}
\item \texttt{img1.png}, \texttt{backup\_img1.png}
\end{enumerate}
\end{alertblock}
\end{frame}
\begin{frame}[label={sec:org1c4e493},fragile]{Brace Expansion}
\begin{definition}[Creating Multiple Arguments]\label{sec:orgde064d7}
Brace expansion generates multiple strings from a pattern. Excellent for bulk creation.
\end{definition}
\begin{block}{Examples}
\begin{verbatim}
# Create multiple files at once
touch file{1,2,3}.txt
# Creates: file1.txt, file2.txt, file3.txt
# Ranges
echo {1..10}
echo {a..z}
# Nested expansion
mkdir -p project/{src,test,docs}
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org90ef838},fragile]{Command History}
\begin{block}{History Features}
\begin{center}
\begin{tabular}{ll}
Key/Command & Action\\
\hline
Up/Down arrows & Navigate history\\
\texttt{history} & Show command history\\
\texttt{!!} & Repeat last command\\
\texttt{!grep} & Execute last command starting with grep\\
Ctrl+R & Reverse search history (The MVP!)\\
\end{tabular}
\end{center}
\end{block}
\end{frame}
\begin{frame}[label={sec:org0ef2dcf},fragile]{History Examples}
\begin{block}{Using History}
\begin{verbatim}
# View last 20 commands
history 20
# Forgot sudo?
$ ls /var/root
ls: /var/root: Permission denied
$ sudo !!
# Search history
(Press Ctrl+R, then type 'ssh')
(reverse-i-search)`ssh': ssh user@umd.edu
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org77dc55a},fragile]{Tab Completion}
\begin{exampleblock}{Productivity Booster}\label{sec:org7559290}
\alert{Tab completion} saves time and prevents typos. If you aren't mashing the Tab key, you're working too hard.
\end{exampleblock}
\begin{block}{How it works}
\begin{itemize}[<+->]
\item Press \texttt{Tab} once to complete a unique match.
\item Press \texttt{Tab} twice to see all possibilities if it's ambiguous.
\item Example: \texttt{cd /u[TAB]l[TAB]b[TAB]} \(\rightarrow\) \texttt{cd /usr/local/bin/}
\end{itemize}
\end{block}
\end{frame}
\begin{frame}[label={sec:orgf2dd0cd}]{Command Substitution}
\begin{definition}[Using Command Output]\label{sec:orgd2f3849}
Command substitution allows you to use the output of a command as an argument to another command.
\end{definition}
\end{frame}
\begin{frame}[label={sec:org102bb11}]{Command Substitution Execution Order}
\begin{block}{How It Works}
\begin{center}
\begin{tikzpicture}[
node distance=0.7cm,
box/.style={rectangle, draw, thick, minimum width=7cm, minimum height=0.6cm, align=center, font=\small\ttfamily}
]
\node[box, fill=blue!15] (original) {tar -czf backup-\$(date +\%Y\%m\%d).tar.gz files/};
\node[box, fill=yellow!20, below=of original] (executed) {\$(date +\%Y\%m\%d) $\rightarrow$ "YYYYMMDD"};
\node[box, fill=green!20, below=of executed] (final) {tar -czf backup-YYYYMMDD.tar.gz files/};
\draw[->, very thick] (original) -- (executed);
\draw[->, very thick] (executed) -- (final);
\end{tikzpicture}
\end{center}
Inner command executes â output replaces substitution â full command runs
\end{block}
\end{frame}
\begin{frame}[label={sec:org1a4be1f},fragile]{Command Substitution Examples}
\begin{block}{Substitution Syntax}
\begin{verbatim}
# Using $(command) syntax (preferred)
echo "Today is $(date)"
files=$(ls -1)
echo "Found $(wc -l < file.txt) lines"
# Using backticks (older syntax)
echo "Today is `date`"
# Nested substitution
echo "User $(whoami) in $(pwd)"
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org107587e},fragile]{Think-Pair-Share: Creative Substitution}
\begin{block}{Scenario}
You want to create a directory named after the current year and month, and then move all your \texttt{.log} files into it.
\end{block}
\begin{exampleblock}{Challenge}\label{sec:org6dd2c1c}
How can you do this in one or two lines using command substitution? (Hint: check \texttt{man date})
\end{exampleblock}
\begin{alertblock}<2->{Answer}
\begin{verbatim}
mkdir "$(date +%Y-%m)"
mv *.log "$(date +%Y-%m)"
\end{verbatim}
\end{alertblock}
\end{frame}
\section*{Pipes and Redirection}
\label{sec:org0b65efc}
\begin{frame}[label={sec:org16185fd},fragile]{Redirection Basics}
\begin{columns}
\begin{column}{0.35\columnwidth}
\begin{block}{Problem}
Output goes to screen and disappears
\end{block}
\end{column}
\begin{column}{0.6\columnwidth}
\begin{exampleblock}{Solution}\label{sec:orgc31c962}
\begin{center}
\begin{tabular}{ll}
Operator & Action\\
\hline
\texttt{>} & Overwrite file\\
\texttt{>{}>{}} & Append to file\\
\texttt{2>} & Redirect errors\\
\texttt{\&>} & Redirect everything\\
\end{tabular}
test/2026-02-04-DRM/the_shell.tex view on Meta::CPAN
\end{frame}
\begin{frame}[label={sec:org2b564ce},fragile]{Building Pipes Step-by-Step}
\begin{block}{Progressive Example}
\begin{verbatim}
# 1. See all lines
$ cat app.log
ERROR: connection failed
INFO: started successfully
ERROR: timeout
# 2. Filter errors only
$ cat app.log | grep ERROR
ERROR: connection failed
ERROR: timeout
# 3. Count errors
$ cat app.log | grep ERROR | wc -l
2
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:org515477a},fragile]{Think-Pair-Share: Debug the Pipeline}
\begin{block}{The Goal}
Find all lines with "Error" in \texttt{app.log} and count them.
\end{block}
\begin{exampleblock}{Broken Commands}\label{sec:orgfd47812}
Identify the flaw in each command:
\begin{enumerate}
\item \texttt{grep "Error" app.log > wc -l}
\item \texttt{cat app.log | grep Error | wc}
\end{enumerate}
\end{exampleblock}
\begin{alertblock}<2->{Answers}
\begin{enumerate}[<+->]
\item \alert{Redirection Error:} \texttt{>} sends output to a \alert{file} named \texttt{wc}. Use \texttt{|} to send to a \alert{program}.
\item \alert{Ambiguous Output:} \texttt{wc} shows lines, words, AND characters. Use \texttt{wc -l} for just lines.
\end{enumerate}
\end{alertblock}
\end{frame}
\section*{xargs}
\label{sec:orge5a0e63}
\begin{frame}[label={sec:orge3a5cde},fragile]{xargs: Bridging the Gap}
\begin{definition}[What is it?]\label{sec:orge01f27c}
\texttt{xargs} builds and executes command lines from standard input. It converts lines of text into \alert{arguments} for another command.
\end{definition}
\begin{block}<2->{Why do we need it?}
Some commands (like \texttt{rm}, \texttt{mkdir}, \texttt{mv}) don't read from standard input. They only accept arguments. \texttt{xargs} bridges this gap.
\end{block}
\end{frame}
\begin{frame}[label={sec:orge4edf8e},fragile]{xargs: Usage and Options}
\begin{block}{Examples}
\begin{verbatim}
# Delete all .tmp files (safe with spaces)
find . -name "*.tmp" -print0 | xargs -0 rm
# Run 1 command per input line (NUL-delimited)
printf '%s\0' dir1 dir2 dir3 | xargs -0 -n 1 mkdir
# Custom placement of arguments (safe with spaces)
find . -maxdepth 1 -name "*.txt" -print0 | xargs -0 -I {} mv "{}" backup/
\end{verbatim}
\end{block}
\begin{exampleblock}<2->{Common Flags}\label{sec:org6389170}
\begin{center}
\begin{tabular}{ll}
Option & Description\\
\hline
\texttt{-n N} & Use at most N args per command\\
\texttt{-I \{\}} & Replace \{\} with the input string\\
\texttt{-0} & Read NUL-delimited input (safe)\\
\texttt{-P N} & Run N processes in parallel (Fast!)\\
\end{tabular}
\end{center}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org3499da7},fragile]{System Health with top}
\begin{block}{Monitoring System Resources}
\texttt{top} displays real-time system statistics: CPU, memory, running processes.
\begin{verbatim}
# macOS: Run top once and exit immediately
$ top -l 1 -n 0
\end{verbatim}
\alert{Flags:} \texttt{-l 1} runs top once (1 iteration). \texttt{-n 0} displays 0 processes (header stats only).
\end{block}
\begin{exampleblock}<2->{Common Use Case}\label{sec:org0285027}
Capture CPU and memory usage in scripts for logging or alerting.
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:orgfa1afbf}]{Section 3: Data Wrangling}
\begin{block}{The Goal}
"Most of your time as a developer is spent moving data from one format to another."
\end{block}
\begin{exampleblock}{Key Objectives}\label{sec:org9e8021c}
\begin{itemize}
\item Transform "messy" logs into structured reports.
\item Clean and filter large datasets without opening heavy editors.
\item Build automated pipelines for repetitive processing.
\end{itemize}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org856e9dd},fragile]{Data Wrangling Overview}
\begin{columns}
\begin{column}{0.45\columnwidth}
\begin{block}{}
Cleaning, transforming, and analyzing data using command-line tools.
\alert{Tasks:}
\begin{itemize}
\item Extract fields
\item Count frequencies
\item Filter \& Transform
\item Reformat output
\end{itemize}
\end{block}
\end{column}
\begin{column}{0.5\columnwidth}
\begin{block}{}
\begin{itemize}
test/2026-02-04-DRM/the_shell.tex view on Meta::CPAN
# Logical conditions (AND/OR)
awk '$1 == "POST" && $9 == 200' access.log
# Range pattern (start, end)
awk '/START/,/END/' data.txt
# Filter by timestamp range and format output
awk '$1 >= "2026-01-20" && $1 <= "2026-01-25" \
{printf "[%s %s] %s\n", $1, $2, substr($0, index($0,$3))}' system.log
\end{verbatim}
\end{block}
\end{frame}
\section*{Shell Scripting}
\label{sec:orgd9b136e}
\begin{frame}[label={sec:org0714907},fragile]{Scripting Basics}
\begin{columns}
\begin{column}{0.45\columnwidth}
\begin{block}{}
\begin{itemize}
\item Automate repetitive tasks
\item Combine multiple commands
\item Add logic (if/loops)
\item Reproducibility
\end{itemize}
\end{block}
\end{column}
\begin{column}{0.5\columnwidth}
\begin{verbatim}
#!/bin/bash
# hello.sh
echo "Hello, $USER!"
echo "Date: $(date)"
\end{verbatim}
\end{column}
\end{columns}
\begin{exampleblock}{Making it Executable}\label{sec:orgaab8643}
\begin{verbatim}
chmod +x hello.sh
./hello.sh
\end{verbatim}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:orgfdf37ff},fragile]{Variables in Scripts}
\begin{block}{Definition and Scope}
\begin{verbatim}
# Definition: No spaces around =
name="STIC Class"
count=42
# Access: Use the $ sign
echo "Welcome to $name"
# Command Substitution: Use $()
current_user=$(whoami)
\end{verbatim}
\end{block}
\begin{alertblock}{Important Rules}
\begin{itemize}
\item \alert{Quotes Matter:} Use \texttt{"\$var"} to prevent word splitting if your variable contains spaces.
\item \alert{Braces:} Use \texttt{\$\{var\}} for clarity or when appending text: \texttt{echo "\$\{name\}\_backup"}.
\end{itemize}
\end{alertblock}
\end{frame}
\begin{frame}[label={sec:orgea5b845},fragile]{Positional Arguments}
\begin{block}{Communicating with Scripts}
\begin{center}
\begin{tabular}{ll}
Variable & Description\\
\hline
\texttt{\$0} & The script name itself\\
\texttt{\$1, \$2..} & First, second arguments\\
\texttt{\$\#} & Number of arguments passed\\
\texttt{\$@} & All arguments as a list\\
\texttt{\$?} & Exit status of the \alert{last} command\\
\end{tabular}
\end{center}
\end{block}
\begin{exampleblock}{Practice: Arg Grep}\label{sec:org8b32bdb}
\begin{enumerate}
\item Create a script that takes a word as \texttt{\$1} and a file as \texttt{\$2} and greps for it.
\item \alert{Answer:} \texttt{grep "\$1" "\$2"}
\item Use \texttt{\$@} for looping over arguments.
\end{enumerate}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org3b60504},fragile]{Logic and Conditionals}
\begin{columns}
\begin{column}{0.5\columnwidth}
\begin{verbatim}
if [ "$1" -gt 10 ]; then
echo "Large"
elif [ -f "$1" ]; then
echo "It's a file"
else
echo "Small/Unknown"
fi
\end{verbatim}
\end{column}
\begin{column}{0.45\columnwidth}
\begin{center}
\begin{tabular}{ll}
Test & True if\ldots{}\\
\hline
\texttt{-f} & Regular file\\
\texttt{-d} & Directory\\
\texttt{-eq} & Equal (numeric)\\
\texttt{-z} & Empty string\\
\texttt{=} & Equal (string)\\
\end{tabular}
\end{center}
\end{column}
\end{columns}
\begin{exampleblock}{Practice: File Safety}\label{sec:org2d0a908}
\begin{enumerate}[<+->]
\item Write a script that checks if a directory exists before creating it.
\item \alert{Answer:} \texttt{if [ ! -d "\$dir" ]; then mkdir "\$dir"; fi}
\end{enumerate}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org4416fa9},fragile]{Iteration (for, while)}
test/2026-02-04-DRM/the_shell.tex view on Meta::CPAN
}
greet "Alice"
\end{verbatim}
\end{column}
\begin{column}{0.48\columnwidth}
\begin{block}{}
\begin{itemize}
\item Use \alert{local} variables
\item Return status (0-255)
\item Arguments are \texttt{\$1, \$2..}
\item Name functions clearly
\end{itemize}
\end{block}
\end{column}
\end{columns}
\begin{exampleblock}{Practice: Math Function}\label{sec:org47c6fc4}
\begin{enumerate}[<+->]
\item Create a function \texttt{square} that prints the square of its first argument.
\item \alert{Answer:} \texttt{square() \{ echo \$((\$1 * \$1)); \}}
\end{enumerate}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org1fa3725},fragile]{Robust Scripting and Debugging}
\begin{columns}
\begin{column}{0.48\columnwidth}
\begin{alertblock}{}
\texttt{set -euo pipefail}
\begin{itemize}
\item \alert{-e}: Exit on error
\item \alert{-u}: Error on unset var
\item \alert{pipefail}: Pipeline fails if ANY part fails
\end{itemize}
\end{alertblock}
\end{column}
\begin{column}{0.48\columnwidth}
\begin{block}{}
\begin{itemize}
\item \alert{set -x}: Print commands
\item \alert{bash -n}: Check syntax
\item \alert{shellcheck}: (External tool) highly recommended!
\end{itemize}
\end{block}
\end{column}
\end{columns}
\begin{exampleblock}{Practice: Safety First}\label{sec:org4491911}
\begin{enumerate}[<+->]
\item What happens if you run \texttt{rm -rf \$DIR/file} and \texttt{\$DIR} is undefined?
\item How does \texttt{set -u} prevent this disaster?
\item \alert{Answer:} Without \texttt{-u}, it runs \texttt{rm -rf /file}. With \texttt{-u}, the script exits immediately.
\end{enumerate}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:orgd26e8ce},fragile]{Example: Auto-Backup}
\begin{block}{A Robust Backup Script}
\begin{verbatim}
#!/bin/bash
set -euo pipefail
DEST="/backups/$(date +%Y-%m-%d)"
mkdir -p "$DEST"
for dir in "$@"; do
if [ -d "$dir" ]; then
echo "Backing up $dir..."
tar -czf "$DEST/$(basename "$dir").tar.gz" "$dir"
else
echo "Warning: $dir is not a directory" >&2
fi
done
\end{verbatim}
\end{block}
\end{frame}
\begin{frame}[label={sec:orgda1cfad},fragile]{Analysis: Auto-Backup}
\begin{exampleblock}{Best Practices}\label{sec:org5a927e5}
\begin{enumerate}
\item \alert{Safety:} \texttt{set -euo pipefail} ensures the script stops if a directory can't be created or a command fails.
\item \alert{Dynamic:} Uses \texttt{\$@} to process any number of folders passed as arguments.
\item \alert{Error Handling:} Redirects warnings to \texttt{stderr} (\texttt{>\&2}) so they don't pollute the standard output.
\item \alert{Clean Paths:} Uses \texttt{basename} to ensure the archive name is clean even if a full path is provided.
\end{enumerate}
\end{exampleblock}
\end{frame}
\begin{frame}[label={sec:org1b64aa0}]{Questions?}
\begin{center}
\Large Thank you!
\vspace{1em}
Ask your questions on \alert{Piazza}
\vspace{0.5em}
\end{center}
\end{frame}
\end{document}
( run in 0.529 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )