-
Notifications
You must be signed in to change notification settings - Fork 0
Module 2: Bash Basics for MRI Neuroimaging
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).
- 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.
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:
-
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.
-
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.
-
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.
Absolute essentials: what you are looking at (3 minutes)
A prompt might look like:
student@machine:~$
-
studentis your username. -
machineis the computer/server name. -
~means “your home directory.” -
$indicates you are a normal user (not an administrator).
A typical command looks like:
command options arguments
Example:
ls -lah data
-
lsis the command. -
-lahare options (also called flags). -
datais an argument (a folder name).
Many terminal actions (especially deletion) do not go to a recycle bin.
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.
If you are not sure what a command does, check help first. (In this tutorial, command is just a placeholder name.)
command --help
Notes:
-
--helpexists 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
qto quit.
pwd
What it does: prints the full path of your current directory.
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:-hmatters most with-l.
A very common combination:
ls -lah
-
-llong format -
-ainclude hidden -
-hreadable sizes
whoami
What it does: prints the account name you are logged in as.
Run:
pwd
ls -lah
whoami
You should be able to explain what each command output means.
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 path: starts with
/(example:/home/student/data) -
Relative path: does not start with
/(example:data) and is interpreted from where you are now.
. means “this directory”
.. means “parent directory” (one level up)
Try:
pwd
cd ..
pwd
What it does: cd .. moves you up one level.
cd -
What it does: returns you to the directory you were in immediately before the last cd.
Do this sequence and explain each step:
cd ~
pwd
cd ..
pwd
cd -
pwd
We will create a folder for this tutorial in your home directory.
cd ~
mkdir -p bash_mri_tutorial
cd bash_mri_tutorial
pwd
-
mkdir NAMEcreates a new directory. -
-pmeans “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
echo "hello"
What it does: prints text to the screen.
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. -
>>appends to the end of a file (adds more lines).
cat participants.csv
What it does: prints the full file to the terminal.
less participants.csv
Inside less:
- Press
qto quit - Press
/, type a word, press Enter to search - Press
nto jump to the next match
Answer:
- What is the difference between
>and>>? - When should you use
lessinstead ofcat?
cp participants.csv data/
What it does: copies participants.csv into the data/ directory.
mv participants.csv data/participants_original.csv
What it does: moves the file and renames it.
Safer practice for beginners:
rm -i data/participants_original.csv
-
-imeans “interactive”: asks you to confirm before deleting.
What it does: deletes the file if you confirm.
Explain what each command does:
cp file1 data/
mv file1 file2
rm -i file2
Neuroimaging datasets often contain many similarly named files. Bash helps you match file patterns.
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
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.
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).
Predict, then run:
ls data/*bold*
ls data/sub-00?_ses-01_task-rest_bold.nii.gz
Create a subject list:
echo -e "sub-001
sub-002
sub-010" > data/subjects.txt
-
echo -eenables interpretation ofas 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
-
-nprints line numbers.
grep -i "SUB-002" data/subjects.txt
-
-iignores case.
A pipe takes the output of one command and sends it into another.
ls data | grep "T1w"
-
ls dataprints filenames indata/. -
|sends that output intogrep. -
grep "T1w"keeps only lines containingT1w.
head -n 2 data/subjects.txt
-
headshows the first lines. -
-n 2means “show 2 lines.”
tail -n 2 data/subjects.txt
-
tailshows the last lines.
Explain what this does, step by step:
ls data | grep "sub-001" | grep "bold"
wc -l data/subjects.txt
-
-lcounts lines.
This is common in neuroimaging to confirm how many subjects/runs you have.
Many commands quietly indicate success/failure. You can check the last command’s exit status:
echo $?
-
0typically 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.
Explain why wc -l is useful when you have a subject list.
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 data/bids -type f -name "*T1w.nii.gz"
-
find data/bidstellsfindwhere to start searching. -
-type fmeans “files” (not directories). -
-name "*T1w.nii.gz"matches filenames ending inT1w.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 5stops searching deeper than 5 directory levels.
Write a find command that lists only *bold.nii.gz files under data/bids.
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_DIRreads 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)
Set:
DERIV_DIR=~/bash_mri_tutorial/results/derivatives
Then create it:
mkdir -p "$DERIV_DIR"
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
Readsdata/subjects.txtline-by-line. Each line is stored in the variableSUBJ. The-roption makesreadtreat 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)runsdateand inserts its output.>>appends.
Check results:
find results -type f -name "*.txt"
tail -n 5 results/logs/pipeline.log
-
tail -n 5shows the last 5 lines of the log.
Open one QC file:
cat results/qc/sub-001/qc.txt
Then explain how the folder name sub-001 got into the path.
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 intoscripts/hello_mri.sh. The<< 'EOF'part is a here-document: everything until the lineEOFis 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
-
chmodchanges permissions. -
+xadds “execute” permission.
Run it:
./scripts/hello_mri.sh
-
./means “run the file from the current directory.”
Edit the script so it prints your subject count using:
wc -l data/subjects.txt
Then rerun the script.
Most commands have manuals.
man ls
- Arrow keys scroll.
-
qquits.
Many commands also provide:
ls --help
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
Do this without copying from earlier sections.
- Create a new folder:
~/bash_mri_tutorial_practice
- Inside it, create:
data/results/scripts/
-
Make a subject list with three subjects in
data/subjects.txt. -
Write a loop that creates:
results/<subject>/qc.txt
and appends a timestamped line into:
results/pipeline.log
- Use
findto verify your output files exist.
If you can do this, you have enough Bash to start real MRI workflows safely.
pwd
ls -lah
cd PATH
mkdir -p DIR
cp SRC DST
mv SRC DST
rm -i FILE
grep -n "pattern" FILE
find ROOT -type f -name "*.nii.gz"
while read -r X; do ...; done < list.txt