Skip to content

Linux Command Line for Bioinformatics

By Bio Help Learning35 min readUpdated FREE

Chapter 2 of 5: Set up your terminal and practice folder

Free videoSign in free to watch this video. No payment needed.Sign in / Create free accountLoading the video…
Chapter 2 video: set up your terminal and project folder · 16 min

What you need

  • A Linux terminal. On Windows 10 (version 2004 or later) or Windows 11, use WSL2 with Ubuntu. On macOS, use the built-in Terminal app. On Linux, open any terminal.
  • About 1 GB of free disk space for this tutorial. Real projects need much more: plan for tens to hundreds of GB.
  • No special software. Every command here is part of a standard Linux system (GNU coreutils, grep, gzip and awk).

Windows: install WSL2 and Ubuntu

Open PowerShell as Administrator (right-click the Start button, choose Terminal (Admin) or Windows PowerShell (Admin)) and run:

bashCopy disabled · Buy the study material or join membership to copy code
wsl --install

Restart when asked. Ubuntu opens and asks you to choose a Linux user name and password. This password is only for Linux; you will need it for sudo commands later. From now on, open Ubuntu from the Start menu to get your terminal.

▸ Go deeper: where your Windows files are inside WSL

Your Windows C: drive appears inside Linux as /mnt/c, so your Windows Downloads folder is /mnt/c/Users/YourName/Downloads. Keep your bioinformatics projects inside the Linux home (~) instead: file access across /mnt/c is much slower, and Windows tools can break Linux line endings. To open your Linux folder in Windows Explorer, run explorer.exe . inside it.

SystemHow to get a terminalWatch out for
Windows 10/11WSL2 + Ubuntu (wsl --install)Keep projects in ~, not /mnt/c
macOSTerminal app (shell: zsh)Some tools differ: use gzip -dc instead of zcat; sed -i '' needs the empty quotes
Linux (Ubuntu, Fedora…)Any terminal appNothing special
Lab server / HPCssh user@server from your terminalDo not run heavy jobs on the login node (Chapter 4)

🔬 Researcher notes

macOS ships BSD versions of core tools, not the GNU versions found on Linux. Most everyday commands behave the same, but options differ for sed, date, stat and zcat (BSD zcat expects old .Z files). For identical behaviour across lab members, install GNU tools (for example conda install -c conda-forge coreutils grep gawk sed) or run analyses on a Linux server.

When you report methods, name the system: for example “Ubuntu 22.04 under WSL2, GNU bash 5.1”. Check versions with bash --version and ls --version.

Step 1: Create your project folder

A clear folder layout keeps raw data safe and results easy to find. We use three folders: data for inputs you never edit, results for everything you create, and scripts for your code.

bashCopy disabled · Buy the study material or join membership to copy code
cd ~
mkdir -p bhl-linux/{data,results,scripts}
cd bhl-linux
ls
  • mkdir: make a directory (folder)
  • -p: create parent folders as needed, and do not complain if they already exist
  • {data,results,scripts}: brace expansion; the shell turns it into three folder names before mkdir runs
OutputSign in free to see the expected output. No payment needed.Sign in / Create free account

🔬 Researcher notes

This layout follows a widely cited recommendation for computational biology projects: raw data read-only, one folder for results, one for code, and a log of what was run (Noble, 2009, PLoS Comput Biol 5(7):e1000424, doi:10.1371/journal.pcbi.1000424). To protect raw data from accidents, you can remove write permission: chmod a-w data/*.

Step 2: Create the practice files

We create five small files that look exactly like real ones: a genome (FASTA), sequencing reads (FASTQ), genes (GTF), variants (VCF) and a sample sheet. They are tiny on purpose, so you can check every answer by eye. The cat > file << 'EOF' form writes everything you type until the line EOF into the file.

The genome (FASTA):

bashCopy disabled · Buy the study material or join membership to copy code
cat > data/genome.fa << 'EOF'
>chr1 example chromosome 1
AAGCCCAATAAACCACTCTGACTGGCCGAATAGGGATATAGGCAACGACATGTGCGGCGA
CCCTTGCGACAGTGACGCTTTCGCCGTTGCCTAAACCTATTTGAAGGAGTCTAGCAGCCG
CAGTAAGGCACAATACCTCGTCCGTGTTAC
>chr2 example chromosome 2
CAGACCAAACAAGACGTCCTCTTCAATGTTTAAATGACCCTCTCGTCATAAAACCTTTCT
ACTATGTGTTCCGCAAGAATCAACAACTAC
>chrM example mitochondrion
AATGGCGCGTCGTGAATAACGCGACGGCTGAGACGAACGGCGCGT
EOF

The reads (FASTQ), six reads of 36 bases:

bashCopy disabled · Buy the study material or join membership to copy code
cat > data/reads_R1.fastq << 'EOF'
@read1/1
GAATGAAGCGCTTAAACAGCTCAGGAGCCAGTCCCC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FF
@read2/1
GAAGCGAATGGTATCGATACGTAGGAGGTGTGCCTT
+
F::FFFFFFFF::FFFFFFFFFFF:FFFFF,,:F,#
@read3/1
CCAACTATTCTTTCCAATCCTACAGATCGGAAGAGC
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FF
@read4/1
CACGAAGTTCACAGAAGTGAGATTATGTCTCGTTTG
+
FFFFFFF::FFFFFFFFFFFF:FFFFFFFF,,:F,#
@read5/1
TCTTTAAGCTNGGTGTGGTGGGCACGACCCTGGACG
+
FFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFF:FF
@read6/1
AATGGAACAGACTTGCTTATGTGGACGTTGTATAGG
+
FFFFFFFFFFFF:FFFFFFFFFFFF:FFFFFFF:FF
EOF

GTF, VCF and sample sheets are tab-separated. Tabs are invisible and easily turn into spaces when text is copied, so we type a | between columns and let the tr command (translate characters) turn every | into a real tab:

bashCopy disabled · Buy the study material or join membership to copy code
cat > data/genes.txt << 'EOF'
chr1|bhl|gene|5|120|.|+|.|gene_id "G001"; gene_name "abcA";
chr1|bhl|exon|5|40|.|+|.|gene_id "G001"; gene_name "abcA";
chr1|bhl|exon|70|120|.|+|.|gene_id "G001"; gene_name "abcA";
chr1|bhl|gene|125|148|.|-|.|gene_id "G002"; gene_name "xyzB";
chr1|bhl|exon|125|148|.|-|.|gene_id "G002"; gene_name "xyzB";
chr2|bhl|gene|10|80|.|+|.|gene_id "G003"; gene_name "lmnC";
chr2|bhl|exon|10|35|.|+|.|gene_id "G003"; gene_name "lmnC";
chr2|bhl|exon|50|80|.|+|.|gene_id "G003"; gene_name "lmnC";
EOF

cat > data/variants.txt << 'EOF'
##fileformat=VCFv4.2
##contig=<ID=chr1,length=150>
##contig=<ID=chr2,length=90>
##INFO=<ID=DP,Number=1,Type=Integer,Description="Read depth">
##FILTER=<ID=LowQual,Description="Low quality">
#CHROM|POS|ID|REF|ALT|QUAL|FILTER|INFO
chr1|12|.|A|T|58|PASS|DP=31
chr1|47|.|G|A|12|LowQual|DP=6
chr1|88|.|T|A|71|PASS|DP=40
chr1|133|.|A|C|45|PASS|DP=22
chr2|21|.|CT|C|38|PASS|DP=18
chr2|64|.|A|C|9|LowQual|DP=4
EOF

cat > data/samples.txt << 'EOF'
sample|condition
S01|control
S02|control
S03|treated
S04|treated
EOF

tr '|' '\t' < data/genes.txt > data/genes.gtf
tr '|' '\t' < data/variants.txt > data/variants.vcf
tr '|' '\t' < data/samples.txt > data/samples.tsv
rm data/*.txt

Finally, compress the reads, because real FASTQ files always arrive compressed:

bashCopy disabled · Buy the study material or join membership to copy code
gzip data/reads_R1.fastq
ls -lh data
Output (dates and user name will differ)Sign in free to see the expected output. No payment needed.Sign in / Create free account

If a file size is different, compare your file with the text above; a missing or extra line is the usual cause. Buyers of the study material get these files (and a larger practice dataset) ready to download.

▸ Go deeper: why the ‘EOF’ is in quotes

Without quotes, the shell would try to expand anything that looks like a variable (for example $1) inside the text. With 'EOF' in single quotes, the text is written exactly as typed. Use quotes whenever the content may contain $, backticks or backslashes.

Step 3: Copy, move, rename and delete

bashCopy disabled · Buy the study material or join membership to copy code
cp data/genome.fa results/genome_copy.fa
mv results/genome_copy.fa results/backup.fa
ls results
rm -i results/backup.fa
  • cp source destination: copy a file (cp -r copies a whole folder)
  • mv source destination: move a file; moving within the same folder is how you rename
  • rm file: delete a file; -i asks for confirmation (type y)
  • rmdir folder: delete an empty folder

Warning: the command line has no recycle bin. rm deletes immediately and permanently, and rm -r deletes whole folders. Never run rm -r with a * until you have checked the exact list with ls first. mv and cp also silently overwrite a destination that already exists; add -i to be asked first.

Step 4: Look inside files without opening them

bashCopy disabled · Buy the study material or join membership to copy code
head -n 4 data/genome.fa
tail -n 2 data/genome.fa
wc -l data/genome.fa data/genes.gtf data/variants.vcf
OutputSign in free to see the expected output. No payment needed.Sign in / Create free account
  • head -n 4: first 4 lines (default 10)
  • tail -n 2: last 2 lines; tail -n +2 means “from line 2 to the end”, handy for skipping a header
  • wc -l: count lines (wc alone also counts words and characters)
  • less -S file: scroll through a file page by page; -S stops long lines wrapping; press q to quit and / to search
  • cat file: print the whole file; fine for tiny files, a bad idea for a 10 GB FASTQ

Compressed files need one extra step. zcat unzips a .gz file on the fly and prints it, without creating an unzipped copy on disk:

bashCopy disabled · Buy the study material or join membership to copy code
zcat data/reads_R1.fastq.gz | head -n 4
OutputSign in free to see the expected output. No payment needed.Sign in / Create free account
▸ Go deeper: why head and zcat are fast even on huge files

These tools stream: they read a small chunk, print it, and read the next chunk. Memory use stays tiny whatever the file size. When head has printed its lines it exits, and zcat stops too, so looking at the first reads of a 20 GB file takes a fraction of a second. Counting all lines still has to read the whole file, so it takes longer, but memory use stays small.

Running head directly on a .gz file prints binary garbage, because the bytes are compressed. Always put zcat (or gzip -dc on a Mac) in front.