Skip to content

Module 2: Bash Basics for MRI Neuroimaging

Jared Tanner edited this page Jan 9, 2026 · 5 revisions

Bash Basics for MRI Neuroimaging (30–60 minutes)

Audience: Undergraduate students with zero experience using terminals, command lines, or Bash.
Goal: Build a practical foundation for MRI neuroimaging work (Linux/HPC workflows, BIDS datasets, running pipelines, reading logs, and scripting safely).


How to use this tutorial

  • Type commands exactly as shown inside code blocks.
  • Do not type the leading $ if you see it in examples; it represents the prompt.
  • After most sections, there is a checkpoint. If you can do it, you’re on track.

Time estimates are approximate. If you are brand new, take your time. Don’t rush through commands. Understand what each command does before you move on.


0) Setup: choose your terminal (3–8 minutes)

For this course, you will typically run commands on UF’s Open OnDemand (OOD) site using its built-in terminal. This avoids local installation and keeps everyone in the same environment.

Choose the option that applies to you:

  1. UF Open OnDemand (recommended for this class)
    Go to the course HPC environment (e.g., ood.rc.ufl.edu) and open the Terminal inside your session.

    • This is the default workflow for nearly everyone in this class.
    • You will be running commands on a UF server, not your personal computer.
  2. macOS Terminal (local terminal)
    Open Terminal (Applications → Utilities → Terminal).

    • This is fine for practicing basic commands locally.
    • For real course datasets and pipelines, you will still use OOD/HPC.
  3. Windows: MobaXterm (local Bash + SSH client)
    Use MobaXterm (Free Edition). It provides:

    • A local terminal that supports many Unix-like commands
    • An SSH client to connect to UF systems (if/when you need it)
      For this class, you will usually still work in OOD, but MobaXterm is a reasonable local option if you want one.

What you should see: a terminal window with a cursor where you can type.


1) Absolute essentials: what you are looking at (3 minutes)

Absolute essentials: what you are looking at (3 minutes)

Prompt

A prompt might look like:

student@machine:~$
  • student is your username.
  • machine is the computer/server name.
  • ~ means “your home directory.”
  • $ indicates you are a normal user (not an administrator).

Command format

A typical command looks like:

command  options  arguments

Example:

ls -lah data
  • ls is the command.
  • -lah are options (also called flags).
  • data is an argument (a folder name).

2) Safety rules that prevent expensive mistakes (5 minutes)

Rule 1: There is no undo

Many terminal actions (especially deletion) do not go to a recycle bin.

Rule 2: Spaces split words

my file.txt is treated as two separate words. To include a space:

  • Quote it: "my file.txt"
  • Or escape the space: my\ file.txt

Best practice: avoid spaces in filenames for research computing.

Rule 3: Get help before running unknown commands

If you are not sure what a command does, check help first. (In this tutorial, command is just a placeholder name.)

command --help

Notes:

  • --help exists for many commands, but not all.
  • Sometimes typing the command with no arguments prints help.

If --help is not available, use the manual system:

man ls
  • Use arrow keys / Page Up / Page Down to scroll.
  • Press q to quit.

We will go over these help options later in the tutorial. It's always best to understand what a command will or should do before trying to run it. It's also a good idea to perform a web search or use an AI tool to explain what a command does or will/might do before running it. When in doubt, check before running something!


3) Where am I? What is here? (8–10 minutes)

pwd — print working directory

pwd

What it does: prints the full path of your current directory.


ls — list directory contents

ls

What it does: lists files and folders in the current directory.

Common options (you will use these constantly):

ls -l
  • -l (“long”): shows details (permissions, owner, size, date).
ls -a
  • -a (“all”): includes hidden items (names starting with .).
ls -h
  • -h (“human-readable”): prints file sizes in readable units (K, M, G).
    Note: -h matters most with -l.

A very common combination:

ls -lah
  • -l long format
  • -a include hidden
  • -h readable sizes

whoami — show your username

whoami

What it does: prints the account name you are logged in as.


Checkpoint (1 minute)

Run:

pwd
ls -lah
whoami

You should be able to explain what each command output means.


4) Moving around: cd and paths (8–10 minutes)

cd — change directory

cd

What it does: moves you to your home directory.

cd ~

What it does: also moves you to your home directory (~ is a shortcut).

cd /

What it does: moves you to the filesystem root directory (/).


Absolute vs relative paths

  • Absolute path: starts with / (example: /home/student/data)
  • Relative path: does not start with / (example: data) and is interpreted from where you are now.

Special directory shortcuts

.   means “this directory”
..  means “parent directory” (one level up)

Try:

pwd
cd ..
pwd

What it does: cd .. moves you up one level.


cd - — go back to the previous directory

cd -

What it does: returns you to the directory you were in immediately before the last cd.


Checkpoint (1–2 minutes)

Do this sequence and explain each step:

cd ~
pwd
cd ..
pwd
cd -
pwd

5) Create a safe practice workspace (4 minutes)

We will create a folder for this tutorial in your home directory.

cd ~
mkdir -p bash_mri_tutorial
cd bash_mri_tutorial
pwd

mkdir — make directory

  • mkdir NAME creates a new directory.
  • -p means “parents”: create any missing parent directories, and do not error if it already exists.

Create common neuroimaging-style subfolders:

mkdir -p data scripts results
ls -lah

6) Creating and viewing files (10–12 minutes)

echo — print text

echo "hello"

What it does: prints text to the screen.


Redirection: > and >>

Redirection sends text into a file.

Create a small CSV file:

echo "subject_id,session,run" > participants.csv
echo "sub-001,ses-01,run-01" >> participants.csv
echo "sub-002,ses-01,run-01" >> participants.csv
  • > writes to a file and overwrites it if it already exists. Be careful with this because it can delete what you already have.
  • >> appends to the end of a file (adds more lines).

cat — print a file’s contents

cat participants.csv

What it does: prints the full file to the terminal.


less — view a file page-by-page (recommended for larger files)

less participants.csv

Inside less:

  • Press q to quit
  • Press /, type a word, press Enter to search
  • Press n to jump to the next match

Checkpoint (1 minute)

Answer:

  • What is the difference between > and >>?
  • When should you use less instead of cat?

7) Copying, moving, and deleting (8–10 minutes)

cp — copy

cp participants.csv data/

What it does: copies participants.csv into the data/ directory.


mv — move (also used to rename)

mv participants.csv data/participants_original.csv

What it does: moves the file and renames it.


rm — remove (delete) (dangerous)

Safer practice for beginners:

rm -i data/participants_original.csv
  • -i means “interactive”: asks you to confirm before deleting.

What it does: deletes the file if you confirm.


Checkpoint (1 minute)

Explain what each command does:

cp file1 data/
mv file1 file2
rm -i file2

8) Wildcards: work with many files at once (6–8 minutes)

Neuroimaging datasets often contain many similarly named files. Bash helps you match file patterns.

touch — create an empty file (or update timestamp)

Create MRI-like filenames:

touch data/sub-001_ses-01_T1w.nii.gz
touch data/sub-001_ses-01_task-rest_bold.nii.gz
touch data/sub-002_ses-01_T1w.nii.gz
touch data/sub-002_ses-01_task-rest_bold.nii.gz

Now list them:

ls -lah data

* — match “any number of characters”

ls data/*.nii.gz

What it does: lists all files in data/ that end with .nii.gz.

ls data/*T1w*

What it does: lists files that contain T1w anywhere in the filename.


? — match exactly one character

ls data/sub-00?_ses-01_T1w.nii.gz

What it does: matches sub-001 and sub-002 (and would match sub-003 if it existed).


Checkpoint (1 minute)

Predict, then run:

ls data/*bold*
ls data/sub-00?_ses-01_task-rest_bold.nii.gz

9) Searching and filtering output (8–10 minutes)

grep — search for matching lines in text

Create a subject list:

echo -e "sub-001
sub-002
sub-010" > data/subjects.txt
  • echo -e enables interpretation of as a newline.
  • > overwrites the file if it already exists.

View it:

cat data/subjects.txt

Search for a pattern:

grep "sub-002" data/subjects.txt

What it does: prints any lines containing sub-002.

Useful options:

grep -n "sub" data/subjects.txt
  • -n prints line numbers.
grep -i "SUB-002" data/subjects.txt
  • -i ignores case.

Pipes: |

A pipe takes the output of one command and sends it into another.

ls data | grep "T1w"
  • ls data prints filenames in data/.
  • | sends that output into grep.
  • grep "T1w" keeps only lines containing T1w.

head and tail — show the start or end of a file

head -n 2 data/subjects.txt
  • head shows the first lines.
  • -n 2 means “show 2 lines.”
tail -n 2 data/subjects.txt
  • tail shows the last lines.

Checkpoint (1–2 minutes)

Explain what this does, step by step:

ls data | grep "sub-001" | grep "bold"

10) Counting and checking: wc and exit status (5–7 minutes)

wc — word/line/byte count

wc -l data/subjects.txt
  • -l counts lines.

This is common in neuroimaging to confirm how many subjects/runs you have.


Exit status (success vs failure)

Many commands quietly indicate success/failure. You can check the last command’s exit status:

echo $?
  • 0 typically means success.
  • Any non-zero value typically means some kind of error.

Try:

grep "sub-999" data/subjects.txt
echo $?

grep prints nothing (no match) and usually returns a non-zero status.


Checkpoint (1 minute)

Explain why wc -l is useful when you have a subject list.


11) Finding files: find (8–10 minutes)

Neuroimaging pipelines often need to locate files in nested folders.

Create a simplified BIDS-like structure:

mkdir -p data/bids/sub-001/ses-01/anat
mkdir -p data/bids/sub-001/ses-01/func
mkdir -p data/bids/sub-002/ses-01/anat
mkdir -p data/bids/sub-002/ses-01/func

Create placeholder files:

touch data/bids/sub-001/ses-01/anat/sub-001_ses-01_T1w.nii.gz
touch data/bids/sub-001/ses-01/func/sub-001_ses-01_task-rest_bold.nii.gz
touch data/bids/sub-002/ses-01/anat/sub-002_ses-01_T1w.nii.gz
touch data/bids/sub-002/ses-01/func/sub-002_ses-01_task-rest_bold.nii.gz

find — search for files by name and type

find data/bids -type f -name "*T1w.nii.gz"
  • find data/bids tells find where to start searching.
  • -type f means “files” (not directories).
  • -name "*T1w.nii.gz" matches filenames ending in T1w.nii.gz.
  • The * inside quotes is a wildcard in the name pattern.

Limit search depth (optional but useful):

find data/bids -maxdepth 5 -type f -name "*.nii.gz"
  • -maxdepth 5 stops searching deeper than 5 directory levels.

Checkpoint (1 minute)

Write a find command that lists only *bold.nii.gz files under data/bids.


12) Variables: the “dataset root” habit (6–8 minutes)

Variables reduce mistakes by keeping important paths in one place.

Set a variable:

BIDS_DIR=~/bash_mri_tutorial/data/bids
echo $BIDS_DIR
  • BIDS_DIR=... assigns a value.
  • No spaces around =.
  • $BIDS_DIR reads the variable’s value.

Use it:

ls -lah "$BIDS_DIR"

Why the quotes?

  • "$BIDS_DIR" is safer if the path contains spaces.

Common neuroimaging variables you will see:

  • BIDS_DIR (raw dataset root)
  • DERIV_DIR (derivatives output root)
  • SUBJECTS_DIR (FreeSurfer subjects directory)

Checkpoint (1 minute)

Set:

DERIV_DIR=~/bash_mri_tutorial/results/derivatives

Then create it:

mkdir -p "$DERIV_DIR"

13) A mini “pipeline” pattern: loop + output + log (10–15 minutes)

This section simulates what real pipelines do:

  • read a subject list
  • make per-subject output folders
  • write logs

Create output/log directories:

mkdir -p results/qc results/logs

Run a loop:

while read -r SUBJ; do
  echo "Processing $SUBJ"
  mkdir -p "results/qc/$SUBJ"
  echo "QC placeholder for $SUBJ" > "results/qc/$SUBJ/qc.txt"
  echo "$(date): finished $SUBJ" >> results/logs/pipeline.log
done < data/subjects.txt

Explain each part:

  • while read -r SUBJ; do ... done < data/subjects.txt
    Reads data/subjects.txt line-by-line. Each line is stored in the variable SUBJ. The -r option makes read treat backslashes literally (safer for text).

  • echo "Processing $SUBJ"
    Prints a progress message.

  • mkdir -p "results/qc/$SUBJ"
    Creates an output directory for that subject.

  • echo "QC placeholder for $SUBJ" > "results/qc/$SUBJ/qc.txt"
    Writes a per-subject QC file. > overwrites if it exists.

  • echo "$(date): finished $SUBJ" >> results/logs/pipeline.log
    Appends a timestamped log line. $(date) runs date and inserts its output. >> appends.

Check results:

find results -type f -name "*.txt"
tail -n 5 results/logs/pipeline.log
  • tail -n 5 shows the last 5 lines of the log.

Checkpoint (2 minutes)

Open one QC file:

cat results/qc/sub-001/qc.txt

Then explain how the folder name sub-001 got into the path.


14) Scripts: saving commands so you can rerun them (8–12 minutes)

In real neuroimaging, you do not want to retype long commands every time. You put them in scripts.

Create a script file:

cat > scripts/hello_mri.sh << 'EOF'
#!/usr/bin/env bash
echo "Hello from a Bash script."
echo "Working directory: $(pwd)"
echo "BIDS files:"
find data/bids -type f -name "*.nii.gz"
EOF

Explain the pieces:

  • cat > scripts/hello_mri.sh << 'EOF'
    Starts writing text into scripts/hello_mri.sh. The << 'EOF' part is a here-document: everything until the line EOF is written into the file. Quoting 'EOF' prevents variable expansion while writing.

  • #!/usr/bin/env bash
    The shebang. It tells the system to run the script using Bash.

Make it executable:

chmod +x scripts/hello_mri.sh
  • chmod changes permissions.
  • +x adds “execute” permission.

Run it:

./scripts/hello_mri.sh
  • ./ means “run the file from the current directory.”

Checkpoint (2 minutes)

Edit the script so it prints your subject count using:

wc -l data/subjects.txt

Then rerun the script.


15) Getting help: man and --help (3–5 minutes)

Most commands have manuals.

man ls
  • Arrow keys scroll.
  • q quits.

Many commands also provide:

ls --help

16) MRI neuroimaging context: what this prepares you for (3–5 minutes)

After this tutorial, you should recognize what commands like these are doing at a high level (examples only):

recon-all -subjid sub-001 -i sub-001_T1w.nii.gz -all
  • Runs a FreeSurfer pipeline for a subject.
fslmaths input.nii.gz -mas mask.nii.gz output_masked.nii.gz
  • Uses FSL to apply a mask.
python scripts/run_qc.py --bids "$BIDS_DIR" --out "$DERIV_DIR"
  • Runs a Python QC script using dataset/output variables.

You are not expected to understand those tools yet. You are expected to be comfortable with:

  • paths
  • file patterns
  • loops
  • logs
  • scripts

17) Final exercise (5–10 minutes)

Do this without copying from earlier sections.

  1. Create a new folder:
~/bash_mri_tutorial_practice
  1. Inside it, create:
  • data/
  • results/
  • scripts/
  1. Make a subject list with three subjects in data/subjects.txt.

  2. Write a loop that creates:

results/<subject>/qc.txt

and appends a timestamped line into:

results/pipeline.log
  1. Use find to verify your output files exist.

If you can do this, you have enough Bash to start real MRI workflows safely.


Quick reference (compact)

Navigation

pwd
ls -lah
cd PATH

Files

mkdir -p DIR
cp SRC DST
mv SRC DST
rm -i FILE

Search and automation

grep -n "pattern" FILE
find ROOT -type f -name "*.nii.gz"
while read -r X; do ...; done < list.txt

Clone this wiki locally