3 Command Line Basics
If the only computer interface you’ve used is a graphical one — clicking folder icons, dragging files into the Trash, double-clicking programs — the cluster’s command line can feel like staring at a blank wall. There are no folders to click. There is no Trash. The whole system is a text prompt waiting for you to type something.
This chapter is for that situation. It walks through the handful of commands that get you from “I just logged in and have no idea what to do” to “I can move around, edit a file, and run a script.” Every example is something you would actually type on Hazel.
Use this chapter as a reference, a cheat sheet is located at the bottom. After a few days of using the command line, the commands here will be muscle memory.
3.1 The Prompt
When you first SSH into the cluster, you’ll see something like this:
[unityid@login01 ~]$That whole line is called the prompt. It is the shell telling you what it knows about your situation:
unityid— your user namelogin01— the machine you’re connected to~— the directory you are currently sitting in (the tilde~is shorthand for your home directory)$— the cursor where you type
When this chapter shows a command starting with $, that just means “type this at the prompt.” Don’t actually type the $.
3.2 Where Am I? — pwd
pwd stands for print working directory. It tells you exactly where you are in the filesystem.
$ pwd
/home/unityidIf you ever feel lost, type pwd. It is the easiest way to get oriented.
3.3 What’s Here? — ls
ls (short for list) shows the contents of the current directory.
$ ls
data scripts results notes.txtls has a handful of options worth knowing:
| Command | What it does |
|---|---|
ls |
List files and directories in the current location |
ls -l |
Long format — shows size, owner, modification time |
ls -a |
Show hidden files (anything starting with a .) |
ls -h |
Human-readable file sizes (use with -l) |
ls -t |
Sort by modification time, newest first |
ls -lrt |
Long format, oldest first, newest at the bottom |
ls /some/path |
List the contents of a different directory |
The flags can be combined: ls -lah is “long format, all files, human-readable sizes.”
$ ls -lh
drwxr-xr-x 2 unityid users 4.0K Apr 12 10:14 data
drwxr-xr-x 2 unityid users 4.0K Apr 12 10:14 scripts
-rw-r--r-- 1 unityid users 1.2K Apr 12 10:14 notes.txtThe first letter of each row tells you the type: d is a directory, - is a regular file.
3.4 Moving Around — cd
cd stands for change directory. It is how you walk through the filesystem.
$ cd data # go into the data folder
$ cd /share/brc # jump to an absolute path
$ cd .. # go up one level
$ cd ~ # go home
$ cd # also goes home (cd with no argument)
$ cd - # go back to the last directory you were inAfter every cd, run pwd and ls until you trust where you are.
3.5 Paths: ~, ., .., and the difference between absolute and relative
Every file on the cluster has a path — a string that says how to find it. Paths use forward slashes / to separate directory names.
An absolute path starts with / and gives the complete location from the very top of the filesystem:
/rs1/researchers/s/smith/project1/reads.fastqA relative path is interpreted starting from your current directory. If you are sitting in /rs1/researchers/s/smith and you type project1/reads.fastq, the shell expands that to the absolute path above.
A few special path shortcuts come up constantly:
| Symbol | Meaning |
|---|---|
~ |
Your home directory (e.g., /home/$USER) |
. |
The current directory |
.. |
The parent directory (one level up) |
/ |
The root of the filesystem |
So cd ../.. goes up two levels, and ./my_script.sh means “the file my_script.sh in the directory I’m currently in.”
When in doubt, use absolute paths in job scripts. Relative paths break the moment you submit a job from a different directory.
3.6 Tab Completion, History, and Editing the Command Line
Before you go any further: learn these shortcuts. They will save you hours.
3.6.1 Tab completion
Press Tab while typing a file or directory name and the shell will finish it for you. Press Tab twice and it will show all the possible completions.
$ cd /rs1/res<Tab>
# becomes:
$ cd /rs1/researchers/This is not just convenience — it’s also how you avoid typos. If Tab doesn’t complete, the file you typed doesn’t exist.
3.6.2 Command history
| Key | What it does |
|---|---|
Up arrow / Down arrow |
Step through previous commands |
Ctrl+R |
Search backwards through your history (type a few letters) |
history |
Print your recent commands |
!! |
Re-run the last command |
!123 |
Re-run command number 123 from history |
3.6.3 Line editing
| Key | What it does |
|---|---|
Ctrl+A |
Jump to the start of the line |
Ctrl+E |
Jump to the end of the line |
Ctrl+C |
Cancel the current command (or kill a running program) |
3.7 Making Directories — mkdir
mkdir creates a new directory.
$ mkdir results
$ mkdir -p project/data/raw # -p makes parent directories as neededThe -p flag is the one to remember. Without it, mkdir project/data/raw fails if project/ doesn’t exist yet. With it, the whole chain is created in one go and mkdir will not complain if the directory already exists.
3.8 Creating and Viewing Files
3.8.1 Make an empty file — touch
$ touch notes.txttouch creates an empty file (or, if the file already exists, updates its modification timestamp).
3.8.2 Quickly write text into a file — echo with >
$ echo "hello world" > greeting.txtThe > is a redirection operator — more on that in Section 3.13.
3.8.3 View a whole file — cat
$ cat greeting.txt
hello worldcat dumps the entire contents of a file to the screen. Fine for small files. For anything more than a few dozen lines, use less instead.
3.8.4 Page through a file — less
$ less results.txtless opens the file in a scrollable viewer. Useful keys inside less:
| Key | Action |
|---|---|
Space / f |
Next page |
b |
Previous page |
g |
Jump to the top |
G |
Jump to the bottom |
/word |
Search forward for “word” |
n / N |
Next / previous search match |
q |
Quit |
3.8.5 Just the first or last few lines — head and tail
$ head reads.fastq # first 10 lines
$ head -n 4 reads.fastq # first 4 lines
$ tail -n 20 job.log # last 20 lines
$ tail -f job.log # follow the file as it grows (Ctrl+C to stop)tail -f is invaluable for watching a log file while a job is running.
3.9 Copying — cp
cp copies a file to a new location.
$ cp notes.txt notes_backup.txt
$ cp notes.txt /share/brc/$USER/notes.txt
$ cp -r project/ project_v2/ # -r for directories
$ cp -p file1 file2 # -p preserves timestamps and permissionsThe -r (recursive) flag is required when copying a directory — without it, cp refuses.
3.10 Moving and Renaming — mv
mv moves a file from one place to another. There is no separate “rename” command — renaming is just moving a file to a new name in the same directory.
$ mv notes.txt notes_old.txt # rename
$ mv notes.txt /share/brc/$USER/ # move to another directory
$ mv *.fastq fastq_files/ # move many files at once (see wildcards below)mv will silently overwrite an existing destination file. Use mv -i to be prompted before any overwrite.
3.11 Deleting — rm
rm deletes a file. This is where the cluster differs sharply from a graphical desktop.
There is no Trash and no Undo on the cluster. When you rm a file, it is gone immediately and permanently. Cluster filesystems generally do not have user-accessible snapshots you can restore from.
$ rm old_results.txt
$ rm -r old_project/ # -r for directories (recursive)
$ rm -i confidential.txt # -i prompts before each deleteYou will see rm -rf in tutorials online — it means “recursive, force, don’t prompt for anything.” It is one of the most dangerous things you can type. Read carefully before using it, especially with paths that include * or variables.
To delete an empty directory, you can also use rmdir, which (unlike rm -r) refuses to delete anything that still has files in it — a useful safety net.
$ rmdir empty_folder/3.12 Wildcards (Globs)
The shell expands certain characters into lists of matching filenames before running your command.
| Pattern | Matches |
|---|---|
* |
Any string of characters (including none) |
? |
Any single character |
[abc] |
Any one character from the set a, b, or c |
[0-9] |
Any single digit |
{red,blue} |
Either red or blue (brace expansion) |
$ ls *.txt # every file ending in .txt
$ ls sample_*.txt # sample_001.txt, sample_abc.txt, ...
$ ls sample_00?.txt # sample_001 through sample_009 only
$ rm *.tmp # delete every .tmp file (be careful!)
$ cp data/*.csv backup/ # copy all csv files into backup/Always preview a wildcard with ls before using it with rm or mv. A space in the wrong place — rm * .tmp instead of rm *.tmp — will delete every file in your directory.
3.13 Pipes and Redirection
A program’s output normally goes to your terminal. With redirection and pipes, you can send that output somewhere else.
3.13.1 Redirecting output to a file
| Operator | Effect |
|---|---|
> file |
Send standard output to file, overwriting it |
>> file |
Append standard output to file |
2> file |
Send standard error to file |
&> file |
Send both stdout and stderr to file |
2>&1 |
Merge stderr into stdout |
< file |
Read input from file instead of the keyboard |
$ ls -l > listing.txt # save the listing to a file
$ echo "run 1 finished" >> log.txt # append a line to a log
$ python script.py > out.log 2> err.log
$ python script.py &> all.log # both streams into one file3.13.2 /dev/null — the trash chute
/dev/null is a special file that throws away anything written to it. Use it to discard output you don’t care about.
$ noisy_command > /dev/null # discard stdout
$ noisy_command 2> /dev/null # discard stderr
$ noisy_command &> /dev/null # discard everything3.13.3 Pipes — chaining commands
The pipe | sends one command’s output directly into the next command’s input. This is what makes the shell powerful: small commands compose into bigger workflows.
$ ls -l | less # page through a long listing
$ cat data.txt | head -n 8 # first 8 lines of data.txt
$ history | tail -n 20 # last 20 commands you ran
$ ls *.txt | wc -l # count how many .txt files exist in the current directoryYou will see pipes constantly in HPC workflows — they’re how data flows between tools without writing intermediate files.
3.14 Editing Files in the Terminal
You will need to edit text files directly on the cluster: job scripts, config files, small notes. There are two editors you should know about.
3.14.1 nano — the friendly one
nano is a small, beginner-friendly editor. The list of available commands is always shown at the bottom of the screen.
$ nano my_script.shInside nano, the ^ symbol means Ctrl:
| Shortcut | What it does |
|---|---|
Ctrl+O then Enter |
Save (Write Out) |
Ctrl+X |
Exit (asks to save if you’ve changed anything) |
Ctrl+K |
Cut the current line |
Ctrl+U |
Paste |
Ctrl+W |
Search |
Ctrl+G |
Help |
If you only learn one editor, learn nano. It is enough to do almost anything.
3.14.2 vim — survival guide
vim is everywhere on Linux systems, including as the default editor for some commands like git. Sooner or later you will open it by accident, and you need to know how to get out.
vim has modes. When it opens, you are in normal mode, where most keys are commands rather than text input. To actually type characters into the file, you have to enter insert mode first.
| To do this | Type this |
|---|---|
| Quit without saving | Esc then :q! then Enter |
| Save and quit | Esc then :wq then Enter |
| Save without quitting | Esc then :w then Enter |
| Enter insert mode (start typing) | i |
| Leave insert mode | Esc |
| Undo | Esc then u |
| Redo | Esc then Ctrl+R |
The single most useful sequence is Esc :q! Enter — that will get you out of vim no matter what state it is in, without saving any changes.
If you prefer not to deal with vim showing up unexpectedly, set your default editor to nano:
$ export EDITOR=nanoAdd that line to ~/.bashrc to make it stick across sessions.
3.15 File Permissions and Making Scripts Executable — chmod
Every file on the cluster has permissions that control who can read, write, and execute it. The ls -l output shows them in the first column:
-rwxr-xr-- 1 unityid users 1024 Apr 12 10:14 my_script.shThe 10 characters break down as:
- Position 1: file type (
-for file,dfor directory) - Positions 2–4: owner permissions (
rwx= read, write, execute) - Positions 5–7: group permissions
- Positions 8–10: everyone else’s permissions
For day-to-day use, the only chmod command most people need is the one that makes a script runnable:
$ chmod +x my_script.shWithout +x, trying to run a script gives Permission denied even if the script is otherwise correct. This is the #1 reason a freshly written script “doesn’t work.”
Other common forms:
$ chmod -x my_script.sh # remove execute permission
$ chmod 644 notes.txt # rw-r--r-- (owner read/write, others read-only)
$ chmod 755 my_script.sh # rwxr-xr-x (typical for scripts)
$ chmod -R 750 my_project/ # apply recursively to a whole directoryThe numeric forms are a shorthand: each digit is read(4) + write(2) + execute(1) for owner/group/everyone. 755 means owner gets 4+2+1=7, group gets 4+1=5, everyone gets 4+1=5.
3.16 Writing and Running a Bash Script
A bash script is just a text file containing shell commands, run from top to bottom. Anything you can type at the prompt, you can put in a script.
3.16.1 A minimal script
Create a file called hello.sh with nano:
$ nano hello.shType the following and save:
#!/bin/bash
echo "Hello from $(hostname)"
echo "Today is $(date)"
echo "I am in $(pwd)"Three things to notice:
- The shebang line (
#!/bin/bash) at the very top tells the system “run this script with bash.” It must be the first line of the file, with no spaces before#!. - Comments start with
#and are ignored by the shell. Use them liberally to explain what your script is doing. $(command)runs a command and substitutes its output into the line. Here it puts the output ofhostname,date, andpwdinto the printed text.
3.16.2 Running the script
There are two ways to run a script. They look similar but mean slightly different things.
# Option 1: explicitly pass it to bash
$ bash hello.sh
# Option 2: mark it executable, then run it directly
$ chmod +x hello.sh
$ ./hello.shThe ./ in front of hello.sh is important. It tells the shell “run the hello.sh that is in this directory.” Without it, the shell would search through $PATH for an installed program called hello.sh and report that none exists.
3.16.3 Variables
Variables hold values. You set them with = (no spaces) and read them with $:
#!/bin/bash
NAME="reads.fastq"
OUT_DIR="/share/brc/$USER/results"
mkdir -p "$OUT_DIR"
echo "Processing $NAME into $OUT_DIR"A few rules that trip people up:
- No spaces around
=.NAME = "x"does not work;NAME="x"does. - Always quote variables when they hold paths:
"$OUT_DIR", not$OUT_DIR. Quoting prevents bugs when paths contain spaces. - Convention is to use
UPPER_CASEfor variables you set yourself.
3.16.4 Arguments
A script can accept arguments from the command line. Inside the script, $1 is the first argument, $2 the second, and so on:
#!/bin/bash
# usage: ./greet.sh NAME
PERSON="$1"
echo "Hello, $PERSON"$ chmod +x greet.sh
$ ./greet.sh Jon
Hello, JonRun scripts on a compute node, not the login node, if they do real work. The bash scripts in this chapter are fine for small, quick tasks — but anything that uses real CPU, memory, or time should be wrapped in a SLURM job script and submitted with sbatch. See the Running Jobs chapter.
3.17 A Worked Example
Here is a small workflow that uses most of what’s in this chapter. It sets up a project directory, copies some input data into it, and writes a small script that counts how many lines each input file has.
# 1. Find out where you are.
# If you just logged into hazel, you should be in your home directory
$ pwd
/home/<unityid>
# If not, navigate there
$ cd ~
# 2. Make a new directory for this project
$ mkdir -p line_counts
$ cd line_counts
$ pwd
/home/<unityid>/line_counts
# 3. Copy in some input files.
$ mkdir -p input
$ cp /rs1/shares/brc/trainings/COS_Compute_Handbook/data/*.fastq input/
$ ls input/
sample_001_R1.fastq sample_001_R2.fastq sample_002_R1.fastq ...
# 4. Write the script
$ nano count_lines.shIn nano, paste:
#!/bin/bash
set -euo pipefail
# Set some variables
IN_DIR="input"
OUT_FILE="line_counts.txt"
# Create an empty output file, or wipe it clean if it already exists.
> "$OUT_FILE"
# Loop over every .fastq file in input/, count its lines, and append the result to OUT_FILE.
for f in "$IN_DIR"/*.fastq; do
n=$(wc -l < "$f")
echo "$f $n" >> "$OUT_FILE"
done
# Print a message at the end so you know the script finished.
echo "Done. Results in $OUT_FILE"Save with Ctrl+O, Enter, then exit with Ctrl+X.
# 5. Make it executable and run it
$ chmod +x count_lines.sh
$ ./count_lines.sh
Done. Results in line_counts.txt
# 6. Look at the results
$ cat line_counts.txt
input/sample_001_R1.fastq 4000
input/sample_001_R2.fastq 4000
input/sample_002_R1.fastq 400
input/sample_002_R2.fastq 400
input/sample_003_R1.fastq 1200
input/sample_003_R2.fastq 1200That’s a complete shell workflow: directories, files, a script, and a result.
3.18 Cheat Sheet
| Task | Command |
|---|---|
| Where am I? | pwd |
| What’s here? | ls, ls -lah |
| Move into a directory | cd directory |
| Move up one level | cd .. |
| Go home | cd ~ or just cd |
| Make a directory | mkdir -p path/to/dir |
| Make an empty file | touch file.txt |
| View a file | cat file.txt, less file.txt |
| First / last lines | head file, tail file, tail -f file |
| Copy a file | cp src dest |
| Copy a directory | cp -r src dest |
| Move / rename | mv src dest |
| Delete a file | rm file (no undo!) |
| Delete a directory | rm -r dir (no undo!) |
| Count lines / words | wc -l file, wc -w file |
| Send output to a file | command > file |
| Append output to a file | command >> file |
| Pipe one command into another | command1 \| command2 |
| Discard output | command > /dev/null 2>&1 |
| Make a script runnable | chmod +x script.sh |
| Run a script | ./script.sh or bash script.sh |
| Edit a file | nano file.txt |
| Get out of vim | Esc :q! Enter |
3.19 Where to Go Next
Once you’re comfortable moving around, viewing files, and running small scripts, the natural next steps are:
- The File Transfer Basics chapter for transferring files to and from the cluster
- The Running Jobs chapter for turning a bash script into a SLURM job
man <command>— every command above has a manual page.man ls,man cp,man bash. Pressqto exit.<command> --help— most commands also accept--helpfor a quick summary