# FASTQ File Naming and Organization: A Reproducibility Guide

By the end of this guide you will have a naming convention you can defend in an audit, a directory layout that survives a project growing from eight samples to eight thousand, and a set of shell commands that prove your renaming did not alter a single byte of sequence data. You will also know how to validate FASTQ structure, check that paired-end mates still match, and record enough provenance that someone else can rebuild your samplesheet from the raw directory alone.

You need a terminal with `bash`, `gzip`, `awk`, `sort`, `xargs`, and `sha256sum` (all standard on Linux and macOS), plus `seqkit` for FASTQ-aware statistics. Install `seqkit` through Bioconda or a static release binary, then confirm it runs. A `git` repository is useful for the samplesheet and mapping tables, not for the reads themselves. No reference genome is needed for anything in this walkthrough.

## What a FASTQ file actually contains

A FASTQ file is a plain text representation of raw sequencing reads, with one quality score for every called base. The format is line-based and strictly four lines per record.

Line 1 is the header. It begins with `@` and carries the read identifier plus platform metadata.
Line 2 is the [nucleotide sequence](/knowledge/molecular-biology/nucleotide-sequence), written 5' to 3' as called by the instrument.
Line 3 is a separator that begins with `+`. Some writers repeat the header there, most leave it bare.
Line 4 is the quality string. It is the same length as line 2, and each character encodes one base's quality.

```
@A00123:45:H7J2LDSX2:1:1101:1408:1023 1:N:0:ACGTACGT
CGGTACGTACGTAGCTAGCTAGGCTAACGTTAGGCATCGATCGTAGCTAGCATCGATCGTACGTAGCTAGCTAGCATCGATCGTAGCTAGCATCGATCGTACGTAGCTAGCATCGATCGTAGCTAGC
+
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
```

Define the terms once, because everything downstream depends on them. A **read** is one molecule (or one cluster) that the sequencer saw. A **base call** is the nucleotide the software assigned at one position. A **Phred quality score** is a logarithmic error probability, computed as Q = -10 × log10(P), where P is the probability that the base call is wrong. A Q30 base has a 1-in-1000 chance of being incorrect. Q40 has a 1-in-10,000 chance.

FASTQ stores those scores as printable ASCII characters. The near-universal encoding today is **Phred+33**, meaning the character's ASCII code minus 33 equals the quality score. The character `I` has ASCII code 73, so 73 - 33 = 40, and that base is Q40. Older pipelines may emit Phred+64, where the subtraction is 64. If you ever see quality strings full of `B`, `h`, or `@` characters in odd places, you have an encoding mismatch, not a sequencing problem.

This four-line contract is what makes FASTQ both simple and fragile. Simple because any text tool can read it. Fragile because anything that inserts a blank line, converts line endings, or truncates a sequence without truncating the quality string produces a file that still looks like FASTQ to `less` but fails silently in an aligner.

## FASTQ vs FASTA: what the extension promises

The most common bioinformatics file formats in a sequencing project are FASTQ, FASTA, BAM, VCF, GFF, and BED. The distinction that matters first is **[FASTQ vs FASTA](/knowledge/bioinformatics/fastq-vs-fasta)**, because both are text, both start with a punctuation character, and both are routinely confused by file-extension heuristics.

FASTA stores sequence and an identifier. It has no quality information. A FASTA record is a `>` header line followed by sequence lines of arbitrary wrapping. FASTA is the format for reference genomes, transcript sets, protein sequences, and assembled contigs. Genomic annotation is usually paired with it in GFF, and standardized annotation formats for emerging analyses are designed to integrate with FASTA and GFF so that results remain comparable across studies [1].

FASTQ stores sequence plus per-base quality. It is the format for raw reads leaving the sequencer. Once you align reads you generally move to BAM, which keeps the quality scores in a binary, indexed container. Some analysis tools accept any of these. STRinNGS, for example, identifies short tandem repeat reads in either BAM or FASTQ and reports read counts per locus [2]. That flexibility is useful, but it also means a mislabeled file can travel several steps before anyone notices.

| Property | FASTQ | FASTA |
|--|--|--|
| Header character | `@` | `>` |
| Lines per record | Exactly 4 | 2 or more, sequence wrapped arbitrarily |
| Quality scores | Yes, one per base, ASCII-encoded | No |
| Typical extensions | `.fastq`, `.fq`, compressed `.fastq.gz` | `.fasta`, `.fa`, `.fna`, `.faa` |
| Typical content | Raw reads from a sequencer | Reference genome, assembly, proteins |
| Reversible conversion | FASTQ to FASTA is lossy (qualities dropped) | FASTA to FASTQ is not possible |
| Primary consumers | Aligners, assemblers, demultiplexers | Annotators, search tools, assembly QC |

The conversion rule is worth memorizing. FASTQ to FASTA is a one-way door. You drop the quality string and, with it, every downstream decision that depends on base confidence. Never convert to FASTA just to make a file smaller or easier to email if there is any chance you will need to realign later.

## The two places a sample name lives

FASTQ identity is recorded twice: in the filename and in the read header. Good organization keeps them consistent. Bad organization lets them drift until nobody can tell which file came from which library.

### Inside the header

A modern Illumina-style header carries colon-delimited fields followed by space-delimited flags.

```
@A00123:45:H7J2LDSX2:1:1101:1408:1023 1:N:0:ACGTACGT
```

Read left to right: instrument ID, run number, flowcell ID, lane, tile, x coordinate, y coordinate. After the first space, `1` is the read number (1 for R1, 2 for R2), `N` means the read passed the filter (`Y` would mean it failed), `0` is a control bit field, and `ACGTACGT` is the index sequence for that cluster.

Platforms differ. Some instruments use a different field order or add a second colon-delimited block for the unique molecular identifier. Header parsing is therefore a bad foundation for a pipeline. Ultraplex deliberately moves UMIs out of the sequence and into the read header during demultiplexing so that duplicate removal can find them later [3]. That is a header-level operation, and it works because the tool controls both ends of the process.

When you align reads, the header is what populates the BAM's read group. Most aligners accept an explicit read group string on the command line, which is safer than trusting the header.

```
@RG	ID:PRJ101.A1.LIB001	SM:PRJ101_A1	LB:LIB001	PL:ILLUMINA	PU:H7J2LDSX2.1
```

The `ID` is the read group identifier, `SM` is the sample, `LB` is the library, `PL` is the platform, and `PU` is the platform unit, usually flowcell plus lane. If two libraries from the same subject end up merged without distinct `LB` values, variant callers will treat them as one library and may mis-handle duplicate marking.

### In the filename

Demultiplexers emit one FASTQ per sample per read direction. The convention that bcl2fastq and its successors have popularized looks like this:

```
SampleName_S1_L001_R1_001.fastq.gz
```

`SampleName` comes from the samplesheet. `S1` is the sample index within the run. `L001` is the lane. `R1` is the read direction. `001` is a chunk number for the case where output is split across multiple files.

That name is fine as a sequencer artifact and poor as a project identifier. It carries no project code, no tissue, no assay, and a sample index that means nothing outside that one run. The `S1` field is the specific trap: two different runs can both contain an `S1`, and if you pool directories carelessly you will overwrite or silently merge unrelated samples.

## A naming convention that survives audits

The goal is a filename that is unique, sortable, human-readable, and machine-parseable without a lookup table. That is achievable with a fixed field order and a strict character set.

### Rules to lock down before the first rename

Use ASCII only. No spaces, no commas, no parentheses, no accented characters. Spaces in filenames break naive `for` loops and get escaped differently by every tool that touches them.

Use one delimiter. Underscores inside fields and a consistent separator between fields works if you never need to parse ambiguity. A pattern like `PRJ101_A1_blood_WGS_LIB001_R1.fastq.gz` uses underscores throughout, and each field is fixed-position when split on `_`.

Fix the read-direction token. Always `_R1` and `_R2`, never `_1` and `_2`, never `_fwd` and `_rev`. Paired-end detection in nearly every pipeline is a regex on that suffix.

Fix the extension. Always `.fastq.gz`, not a mix of `.fq`, `.fastq`, and `.fq.gz`. Mixed extensions are the single most common reason a wildcard misses half the files.

Never encode status in the name. No `_final`, `_final2`, `_FINAL_use_this`, `_old`, or dates. Status belongs in the samplesheet or in a manifest, not in a filename that other scripts will glob.

Keep the mapping table under version control. Strict version control is one of the practices identified in clinical bioinformatics consensus recommendations as necessary for reproducibility and comparability, alongside standardized file formats [4]. A rename map is exactly the kind of small text file that should live in `git` while the reads live in object storage.

### The recommended pattern

```
{project}_{subject}_{tissue}_{assay}_{library}_R{1|2}.fastq.gz
```

| Field | Example | Why it exists |
|--|--|--|
| project | `PRJ101` | Separates cohorts and prevents cross-project collisions |
| subject | `A1` | Ties the file to a participant or animal ID |
| tissue | `blood` | Distinguishes sample types from the same subject |
| assay | `WGS` | Distinguishes library prep protocols |
| library | `LIB001` | Distinguishes technical replicates |
| read | `R1` | Required for pairing logic |
| extension | `.fastq.gz` | Required for tool detection |

Two formulas cover most bookkeeping. The number of records in a valid FASTQ equals the number of lines divided by four. The number of FASTQ files for a paired-end library equals two per library, before any lane splitting.

Keep the samplesheet as the authoritative mapping from filename to sample metadata, and treat the filename as a convenience index. A samplesheet with columns `sample_id`, `subject_id`, `tissue`, `library_id`, `read_group`, `fastq_1`, `fastq_2` is enough to drive most workflow managers and to reconstruct the run later.

## Step by step: build, rename, and verify a FASTQ set

The commands below assume a project directory called `prj101` containing a `raw/` folder with demultiplexer output. Work from the project root throughout.

### Step 1: create the layout and inventory the raw files

```bash
mkdir -p prj101/{raw,meta,logs,results,config}
cd prj101
find raw -type f -name "*.fastq.gz" -printf "%P\t%s\n" | sort > meta/raw_inventory.tsv
wc -l meta/raw_inventory.tsv
```

Expected output, for a four-sample paired-end run:

```
8 meta/raw_inventory.tsv
```

The `%P` directive strips the `raw/` prefix so the inventory holds relative names, and `%s` records byte size. Sizes are a cheap sanity check. In a paired-end run, R1 and R2 files should be within a few percent of each other. A file that is half the size of its mate usually means a truncated transfer, not a biological difference.

### Step 2: fingerprint the content before you touch the names

```bash
find raw -type f -name "*.fastq.gz" -print0 | sort -z | xargs -0 sha256sum > meta/raw_checksums.sha256
head -n 2 meta/raw_checksums.sha256
```

Expected output, with hashes truncated here:

```
9f2c1a...  raw/A1_S1_L001_R1_001.fastq.gz
4b7e03...  raw/A1_S1_L001_R2_001.fastq.gz
```

`find -print0` and `xargs -0` are not decoration. They handle filenames containing spaces or special characters that would otherwise split mid-name. `sort -z` keeps the order deterministic across runs so the checksum file itself is reproducible.

Use SHA-256 rather than MD5. MD5 is faster and still fine for detecting accidental corruption, but it has known collision weaknesses and no reason remains to prefer it for new work.

### Step 3: write the rename map as a reviewed text file

```bash
cat > meta/rename_map.tsv <<'EOF'
old_name	new_name
A1_S1_L001_R1_001.fastq.gz	PRJ101_A1_blood_WGS_LIB001_R1.fastq.gz
A1_S1_L001_R2_001.fastq.gz	PRJ101_A1_blood_WGS_LIB001_R2.fastq.gz
B2_S2_L001_R1_001.fastq.gz	PRJ101_B2_blood_WGS_LIB001_R1.fastq.gz
B2_S2_L001_R2_001.fastq.gz	PRJ101_B2_blood_WGS_LIB001_R2.fastq.gz
EOF
column -t -s $'\t' meta/rename_map.tsv
```

The `column` call is a readability check, not a data step. Read the whole map before running it. Renaming errors are cheap to fix now and expensive after three pipelines have consumed the files.

Second tab-separated column values are the new basenames. This map is the artifact you commit to `git`. It documents, in one place, that `A1_S1_L001_R1_001.fastq.gz` became `PRJ101_A1_blood_WGS_LIB001_R1.fastq.gz` on a specific date.

### Step 4: rename with collision checks

```bash
tail -n +2 meta/rename_map.tsv | while IFS=$'\t' read -r old new; do
  src="raw/$old"
  dst="raw/$new"
  if [ ! -f "$src" ]; then
    echo "MISSING $src" >> logs/rename.log
    continue
  fi
  if [ -e "$dst" ]; then
    echo "COLLISION $dst" >> logs/rename.log
    continue
  fi
  mv "$src" "$dst" && echo "OK $old -> $new" >> logs/rename.log
done
grep -c '^OK' logs/rename.log
```

Expected output:

```
8
```

`IFS=$'\t'` sets the field separator to a tab so that the read does not mangle anything containing spaces. `tail -n +2` skips the header row. The collision check matters most: without it, `mv` will happily overwrite an existing file and you will lose data with no error message. Writing failures to a log rather than calling `exit` avoids a subtle trap, because the loop body runs in a subshell created by the pipe and an `exit` there terminates only the subshell.

If the count of `OK` lines does not equal the number of data rows in the map, inspect `logs/rename.log` for `MISSING` or `COLLISION` entries before continuing.

### Step 5: prove the content is unchanged

Renaming must not change a single byte. Because SHA-256 hashes content rather than names, the before and after hash sets should be identical.

```bash
find raw -type f -name "*.fastq.gz" -print0 | sort -z | xargs -0 sha256sum | awk '{print $1}' | sort > meta/hashes_after.txt
awk '{print $1}' meta/raw_checksums.sha256 | sort > meta/hashes_before.txt
diff meta/hashes_before.txt meta/hashes_after.txt && echo "content identical"
```

Expected output:

```
content identical
```

`diff` produces no output when the files match, and the `&&` means the confirmation message prints only on success. If you see a diff, stop and restore from your backup copy. Something rewrote or truncated a file.

### Step 6: validate FASTQ structure and count reads

```bash
seqkit stats -a raw/*.fastq.gz | tee logs/seqkit_stats.txt
```

Expected output, with illustrative numbers that will differ on your data:

```
file                                      format  type  num_seqs    sum_len  min_len  avg_len  max_len  Q1  Q2  Q3  sum_gap  N50  Q20(%)  Q30(%)  GC(%)
raw/PRJ101_A1_blood_WGS_LIB001_R1.fastq.gz  FASTQ   DNA  1,204,338  181,854,138  150  151.0  150  ...   150  98.61   94.27   41.20
raw/PRJ101_A1_blood_WGS_LIB001_R2.fastq.gz  FASTQ   DNA  1,204,338  181,854,138  150  151.0  150  ...   150  98.62   94.31   41.24
```

The columns that matter for naming work are `num_seqs`, which must match between R1 and R2, and `avg_len`, which should be close to your expected read length. `seqkit stats -a` also fails loudly when a record's sequence and quality lines differ in length, which is the most common structural corruption in FASTQ.

For an explicit structural check that does not rely on a third-party tool, decompress and inspect the four-line contract directly:

```bash
for f in raw/*.fastq.gz; do
  gzip -dc "$f" | awk -v name="$f" '
    NR % 4 == 1 && substr($0,1,1) != "@" { print name ": bad header at line " NR; bad=1 }
    NR % 4 == 3 && substr($0,1,1) != "+" { print name ": bad separator at line " NR; bad=1 }
    END { exit bad }
  ' || echo "FAILED: $f"
done
echo "structure check complete"
```

Expected output when everything is clean:

```
structure check complete
```

No per-file lines means no violation was found. Any `bad header` or `bad separator` line tells you the file is not line-aligned, and any `FAILED:` line names the offending file. A truncated final record is the usual cause, and re-downloading from the source is the fix.

### Step 7: confirm the pairs are intact

```bash
seqkit stats -a -T raw/*.fastq.gz | awk -F'\t' '
  NR > 1 {
    key = $1
    sub(/_R1\.fastq\.gz$/, "", key)
    sub(/_R2\.fastq\.gz$/, "", key)
    if ($1 ~ /_R1\.fastq\.gz$/) r1[key] = $4
    else if ($1 ~ /_R2\.fastq\.gz$/) r2[key] = $4
    seen[key] = 1
  }
  END {
    for (k in seen) {
      if (r1[k] == "" || r2[k] == "") print "MISSING MATE: " k
      else if (r1[k] != r2[k]) print "COUNT MISMATCH: " k " R1=" r1[k] " R2=" r2[k]
      else print "OK: " k " " r1[k] " reads per mate"
    }
  }'
```

Expected output:

```
OK: raw/PRJ101_A1_blood_WGS_LIB001 1204338 reads per mate
OK: raw/PRJ101_B2_blood_WGS_LIB001 1180722 reads per mate
```

The `-T` flag requests tabular output, and column 4 is `num_seqs` in that layout. Counts must match exactly for paired-end data. A small mismatch, on the order of a handful of reads, can come from filtering that treats mates independently. A large mismatch means the files are not actually mates, or one was truncated.

### Step 8: build the samplesheet from the filenames

```bash
printf 'sample_id\tsubject_id\ttissue\tassay\tlibrary_id\tread_group\tfastq_1\tfastq_2\n' > meta/samplesheet.tsv
for r1 in raw/*_R1.fastq.gz; do
  r2="${r1/_R1.fastq.gz/_R2.fastq.gz}"
  base=$(basename "$r1" _R1.fastq.gz)
  sample="${base%_*_*_*}"
  printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
    "$sample" "${sample%%_*}_${sample#*_}" blood WGS "${base##*_}" \
    "${sample}.${base##*_}" "$r1" "$r2" >> meta/samplesheet.tsv
done
column -t -s $'\t' meta/samplesheet.tsv | head -n 3
```

Filename parsing with shell parameter expansion is fast but brittle. If your field order ever changes, the parser breaks silently. That is the argument for generating the samplesheet from the reviewed rename map instead of from the filenames, and for validating the result against a known sample count.

```bash
awk -F'\t' 'NR>1{print $1}' meta/samplesheet.tsv | sort | uniq -d
```

Expected output is empty. Any printed value is a duplicate sample ID, which will cause a merge step to fail or, worse, to silently drop a library.

### Step 9: record provenance

```bash
{
  date -u +%Y-%m-%dT%H:%M:%SZ
  seqkit version
  gzip --version | head -n 1
  uname -srm
  sha256sum meta/rename_map.tsv meta/samplesheet.tsv
} > logs/provenance.txt
cat logs/provenance.txt
```

Expected output, with values that reflect your machine:

```
2026-11-10T14:02:11Z
seqkit v2.8.2
gzip 1.12
Linux 6.8.0-45-generic x86_64
c1d0...  meta/rename_map.tsv
77ab...  meta/samplesheet.tsv
```

Tool versions and input hashes are the minimum provenance for a rerun. Recording them costs seconds and saves hours when a collaborator reports that your counts do not match theirs. Containerized workflows extend this idea, pinning third-party tools inside version-controlled images so that the environment itself is reproducible rather than merely documented [5].

## Directory layout that scales past one batch

A flat `raw/` folder works until the second sequencing batch arrives. Adopt a layout with a read-only raw layer and a clear separation between inputs, metadata, and derived outputs.

```
prj101/
  raw/          raw FASTQ, never edited in place
  meta/         rename maps, samplesheets, checksums, provenance
  config/       pipeline configuration files
  results/      alignments, counts, reports
  logs/         tool output and run logs
```

Three habits make this layout durable. First, treat `raw/` as read-only after the checksum step, and change permissions to enforce it (`chmod -R a-w raw`). Second, never let derived files inherit raw names, because `PRJ101_A1_blood_WGS_LIB001_R1.fastq.gz` and a BAM of the same sample should not be distinguishable only by a directory. Third, keep every configuration file in `config/` under version control.

Declarative configuration is what makes this portable. A workflow encoded as a single shareable configuration file lets another lab reproduce the exact processing steps without reverse-engineering a shell history, which is the approach taken by reproducible spectral processing frameworks [6]. The same principle applies to a FASTQ pipeline: the samplesheet plus the config file plus the tool versions is the complete recipe.

## How standardized formats and validation fit the reproducible picture

Naming is necessary but not sufficient. Reproducibility also depends on standardized file formats and on validating the formats you receive.

Clinical bioinformatics consensus recommendations from the Nordic Alliance for Clinical Genomics emphasize standardized file formats and strict version control as core requirements for reproducible and comparable results in production settings [4]. Those recommendations come from units running diagnostic pipelines, and the logic transfers directly to research: if the file name and the file format are both unpredictable, no downstream comparison is trustworthy.

Validation should be a pipeline step, not a manual spot check. AssemblyQC, a Nextflow pipeline for genome assembly quality reporting, begins with file-format validation before any quality metric is computed, and it adheres to nf-core community conventions for reproducibility [7]. The lesson is structural: validate first, then analyze, and make the validation part of the recorded workflow rather than a note in a [lab notebook](/knowledge/molecular-biology/lab-notebook).

Standardized output naming matters as much as standardized input naming. Public health bioinformatics workflows built for Terra are written to generate outputs in standardized file formats and keep version-controlled code in public repositories, so that results can be validated and audited [8]. When someone downstream receives your BAM, VCF, and counts table, the names should tell them which sample and which pipeline version produced each file without a phone call.

Containerization closes the loop. CREDO generates Dockerfiles for bioinformatics tools and stores package information and dependencies in a GitHub-compatible format so that images can be rebuilt from scratch and remain reproducible [9]. The file naming question and the environment question are the same question asked at different scales: can someone else reconstruct exactly what you did from artifacts that still exist.

Annotation and reporting formats deserve the same treatment. DeNoFo defines a standardized annotation format that integrates with established formats such as FASTA and GFF, which makes datasets comparable across studies that previously used incompatible conventions [1]. Configurable annotation frameworks likewise expose control over output formats and evidence traceability so that results can be audited rather than merely displayed [10]. Every one of those outputs traces back to a FASTQ file with a name that either resolved cleanly or did not.

## Where names are born: demultiplexing

The naming decision is often made before you see the data. Demultiplexing is the process of splitting a raw sequencing file into per-sample files using sample-specific barcodes, and it is the first step of virtually every next-generation sequencing analysis [3].

Ultraplex is a demultiplexer designed for exactly this step. It splits a raw FASTQ containing barcodes at one end or at both the 5' and 3' ends, trims adapters and low-quality bases, and moves UMIs into the read header so that PCR duplicates can be removed later. It handles single-end and paired-end data and can process an entire Illumina HiSeq lane of nearly 500 million reads in under 20 minutes [3]. Throughput matters here because the naming convention you choose has to be applied consistently at that scale, across lane splits and read chunks, without manual intervention.

Two practical rules follow from how demultiplexers behave. First, define the output naming pattern in the demultiplexer configuration rather than renaming thousands of files afterward. Second, keep the demultiplexing statistics report, because it records how many reads were assigned to each sample and how many were unassigned. A sample that received far fewer reads than its library concentration predicted is a red flag that belongs in the run record, not discovered six months later.

## Common Mistakes and Limitations

**Renaming before checksumming.** If you rename first and something goes wrong, you have no content baseline to compare against. Always hash the raw files before any filesystem change.

**Trusting the `S1` sample index.** The `_S1_` field is run-local. Pooling two runs that both contain `A1_S1` produces either an overwrite or a silent merge depending on the tool. Project and library fields are what make a name globally unique.

**Mixing extensions.** A directory containing `.fq`, `.fastq`, `.fq.gz`, and `.fastq.gz` will be partially processed by any wildcard that assumes one form. Pick `.fastq.gz` and convert everything else once, at intake.

**Encoding spaces or sample descriptions in filenames.** `Sample A1 (blood, rep 2).fastq.gz` will break a `for` loop, an R `list.files` call, and a Nextflow channel in three different ways. Replace with underscores before the file enters the project.

**Assuming the filename and the header agree.** After a rename, the header still carries the original instrument and index metadata. That is correct and expected, but it means you cannot reconstruct the original filename from the header alone. Keep the rename map.

**Trusting `wc -l` on a compressed file.** `wc -l` on a `.gz` returns the number of compressed lines, which is meaningless. Either decompress first or use a FASTQ-aware tool.

**Skipping the mate-count check.** Counts that differ by a few reads look harmless and often are, but they also look identical to a truncated file. Check every time and investigate every mismatch.

**No backup before bulk operations.** A `for` loop with a subtle quoting bug can rename hundreds of files into a single name. Verify the map on one sample in a scratch directory first.

**Treating MD5 as a security control.** MD5 detects accidental corruption adequately for many uses, but it is not a cryptographic integrity guarantee. Use SHA-256 for provenance records.

**Assuming a naming convention is self-enforcing.** Conventions decay when a new person joins and writes a quick script. Enforce with a validator that runs in the pipeline and fails on any filename that does not match the pattern.

The limitations are real. A naming convention cannot fix a samplesheet that was wrong at the bench, and it cannot recover a library that was mislabeled before sequencing. It also cannot resolve genuinely ambiguous cases, such as two aliquots of the same library sequenced on different flowcells, without an explicit `library_id` field. Those cases need a lab record, not a cleverer filename.

## Frequently Asked Questions

### Should FASTQ files use .fq or .fastq?

Use `.fastq` with `.fastq.gz` for compression and apply it consistently across the project. `.fq` is not wrong and some tools accept it, but mixing the two creates wildcard gaps that silently exclude files from analysis.

### Can I rename FASTQ files after alignment has been run?

Yes, the reads are unaffected, but the BAM header still carries the old sample and read group names. Rename before alignment whenever possible. If you must rename afterward, update the samplesheet and read group definitions together so they do not drift apart.

### What do R1 and R2 mean in a FASTQ filename?

R1 is the forward read and R2 is the reverse read from the same library fragment in paired-end sequencing. They are always produced in matched pairs, so counts must be identical between mates.

### How do I tell a FASTQ file from a FASTA file?

Check the first character and the line count. FASTQ records begin with `@` and occupy exactly four lines, including a quality string. FASTA records begin with `>` and have no quality line.

### Do I need the lane and read number in the filename?

The read number is essential because it drives pairing. The lane is only necessary if the same library was sequenced across multiple lanes that you intend to keep separate. If you merge lanes at intake, record that merge in the samplesheet rather than dropping the information.

### Where should the sample name live, in the filename or in the header?

Both, and they should be consistent. The filename drives file-level tooling and globbing. The header, or an explicit read group string passed to the aligner, drives sample and library identity inside BAM files. Treat the samplesheet as the authority that keeps them aligned.

### How do I check that a paired-end FASTQ pair is intact?

Compare record counts between R1 and R2, which should be exactly equal, and confirm both files pass a four-line structural check. `seqkit stats -a` reports read counts and flags sequence and quality length mismatches.

### Is it safe to store FASTQ files compressed?

Yes, gzip compression is standard and lossless, and virtually every tool reads `.fastq.gz` directly. Keep the compression level and gzip version in your provenance record so that checksums remain reproducible across environments.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Should FASTQ files use .fq or .fastq?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use .fastq with .fastq.gz for compression and apply it consistently across the project. .fq is not wrong and some tools accept it, but mixing the two creates wildcard gaps that silently exclude files from analysis."
      }
    },
    {
      "@type": "Question",
      "name": "Can I rename FASTQ files after alignment has been run?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, the reads are unaffected, but the BAM header still carries the old sample and read group names. Rename before alignment whenever possible. If you must rename afterward, update the samplesheet and read group definitions together so they do not drift apart."
      }
    },
    {
      "@type": "Question",
      "name": "What do R1 and R2 mean in a FASTQ filename?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "R1 is the forward read and R2 is the reverse read from the same library fragment in paired-end sequencing. They are always produced in matched pairs, so counts must be identical between mates."
      }
    },
    {
      "@type": "Question",
      "name": "How do I tell a FASTQ file from a FASTA file?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Check the first character and the line count. FASTQ records begin with @ and occupy exactly four lines, including a quality string. FASTA records begin with > and have no quality line."
      }
    },
    {
      "@type": "Question",
      "name": "Do I need the lane and read number in the filename?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "The read number is essential because it drives pairing. The lane is only necessary if the same library was sequenced across multiple lanes that you intend to keep separate. If you merge lanes at intake, record that merge in the samplesheet rather than dropping the information."
      }
    },
    {
      "@type": "Question",
      "name": "Where should the sample name live, in the filename or in the header?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Both, and they should be consistent. The filename drives file-level tooling and globbing. The header, or an explicit read group string passed to the aligner, drives sample and library identity inside BAM files. Treat the samplesheet as the authority that keeps them aligned."
      }
    },
    {
      "@type": "Question",
      "name": "How do I check that a paired-end FASTQ pair is intact?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Compare record counts between R1 and R2, which should be exactly equal, and confirm both files pass a four-line structural check. seqkit stats -a reports read counts and flags sequence and quality length mismatches."
      }
    },
    {
      "@type": "Question",
      "name": "Is it safe to store FASTQ files compressed?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, gzip compression is standard and lossless, and virtually every tool reads .fastq.gz directly. Keep the compression level and gzip version in your provenance record so that checksums remain reproducible across environments."
      }
    }
  ]
}
</script>

## Sources

1. [DeNoFo: a file format and toolkit for standardized, comparable de novo gene annotation.](https://pubmed.ncbi.nlm.nih.gov/41051215/)
2. [Introduction of the Python script STRinNGS for analysis of STR regions in FASTQ or BAM files and expansion of the Danish STR sequence database to 11 STRs.](https://pubmed.ncbi.nlm.nih.gov/26722765/)
3. [Ultraplex: A rapid, flexible, all-in-one fastq demultiplexer.](https://pubmed.ncbi.nlm.nih.gov/34286104/)
4. [Recommendations for bioinformatics in clinical practice.](https://pubmed.ncbi.nlm.nih.gov/41107899/)
5. [MStargetR: a reproducible, containerised workflow for end-to-end targeted (MRM/SRM) mass spectrometry data processing in R.](https://pubmed.ncbi.nlm.nih.gov/42791429/)
6. [TRaP: An Open-source, Reproducible Framework for Raman Spectral Preprocessing across Heterogeneous Systems.](https://pubmed.ncbi.nlm.nih.gov/41928941/)
7. [AssemblyQC: a Nextflow pipeline for reproducible reporting of assembly quality.](https://pubmed.ncbi.nlm.nih.gov/39078114/)
8. [Accelerating bioinformatics implementation in public health.](https://pubmed.ncbi.nlm.nih.gov/37428142/)
9. [CREDO: a friendly Customizable, REproducible, DOcker file generator for bioinformatics applications.](https://pubmed.ncbi.nlm.nih.gov/38475691/)
10. [FANTASIA suite: a reproducible and configurable framework for embedding-based functional annotation of proteins.](https://pubmed.ncbi.nlm.nih.gov/42729796/)