Skip to content

Tutorial: shell pipeline

This tutorial records a small CSV summary generated by Bash and awk. It demonstrates the same evidence workflow as a Python experiment without implying that SciProof understands the pipeline’s language or manages its dependencies.

Run these commands from the repository root on a POSIX-like system with Bash, awk, and SciProof installed from this checkout:

Terminal window
python -m pip install -e .
mkdir -p examples/shell_pipeline/out

The input is intentionally tiny and deterministic. The script reads it and writes one exact CSV output plus one JSON numeric output.

examples/shell_pipeline/data.csv:

sample,value
sample-a,10
sample-b,20
sample-c,30

examples/shell_pipeline/analyze.sh:

#!/usr/bin/env bash
set -eu
input=$1
csv_output=$2
json_output=$3
mkdir -p "$(dirname "$csv_output")" "$(dirname "$json_output")"
awk -F, -v csv="$csv_output" -v json="$json_output" '
NR == 1 { next }
NF != 2 || $1 == "" { exit 2 }
{
count++
total += $2
}
END {
if (count == 0) exit 3
mean = total / count
printf "count,total,mean\n%d,%.0f,%.2f\n", count, total, mean > csv
printf "{\n \"count\": %d,\n \"total\": %.0f,\n \"mean\": %.2f\n}\n", count, total, mean > json
}
' "$input"

Declare the script and data as inputs, the human-readable CSV as an exact output, and the JSON as a numeric output. --note records the tool versions because SciProof does not infer Bash or awk versions from a non-Python command.

Terminal window
sciproof capture --name shell-pipeline \
--input examples/shell_pipeline/analyze.sh \
--input examples/shell_pipeline/data.csv \
--output examples/shell_pipeline/out/summary.csv \
--output-numeric examples/shell_pipeline/out/summary.json \
--note "bash: $(bash --version | head -n 1)" \
-- bash examples/shell_pipeline/analyze.sh \
examples/shell_pipeline/data.csv \
examples/shell_pipeline/out/summary.csv \
examples/shell_pipeline/out/summary.json

Inspect the files the command created:

Terminal window
cat examples/shell_pipeline/out/summary.csv
cat examples/shell_pipeline/out/summary.json

The pipeline was run with the sample input. Its file output was:

count,total,mean
3,60,20.00
{
"count": 3,
"total": 60,
"mean": 20.00
}

The --note records the Bash version. SciProof cannot infer the awk implementation or its version; if that matters for your experiment, record it separately using the method provided by your operating system or package manager. The exact capture transcript and manifest timestamp depend on the machine and SciProof version, so do not copy a timestamp or digest from another run.

3. Understand the manifest’s environment section

Section titled “3. Understand the manifest’s environment section”

For a non-Python command, SciProof cannot probe the interpreter that executes the experiment. The manifest’s environment section describes the Python interpreter running SciProof itself; it does not claim that this Python interpreter ran the shell pipeline, and it does not inventory Bash, awk, or other operating-system tools. The command is recorded separately.

The --note above stores the Bash version string as human-supplied context. Notes are not independently verified, so record the versions accurately and keep any relevant lockfiles or toolchain definitions among the declared inputs.

4. Verify without rerunning, then rerun in a clean environment

Section titled “4. Verify without rerunning, then rerun in a clean environment”

Integrity verification checks the declared files without executing the recorded command:

Terminal window
sciproof verify shell-pipeline.sciproof.json

To execute the recorded command again with SciProof’s reduced environment, explicitly opt in:

Terminal window
sciproof verify shell-pipeline.sciproof.json --rerun --clean-env --yes

A clean environment limits inherited environment variables; it is not a sandbox. Only rerun a manifest whose command you trust. This example uses a local script you just inspected.

Change one declared input value and run integrity verification again:

Terminal window
cat > examples/shell_pipeline/data.csv <<'EOF'
sample,value
sample-a,11
sample-b,20
sample-c,30
EOF
sciproof verify shell-pipeline.sciproof.json

The verdict should be FAIL because the declared input’s SHA-256 digest no longer matches the captured evidence. Restore the original input before continuing:

Terminal window
cat > examples/shell_pipeline/data.csv <<'EOF'
sample,value
sample-a,10
sample-b,20
sample-c,30
EOF
sciproof verify shell-pipeline.sciproof.json

The final integrity check should return to PASS. The manifest itself is not a lockfile and SciProof does not install Bash or awk; the note is context, not environment reconstruction.

As always, a PASS means only that the checks that were performed agree with the evidence. It does not establish that the calculation is scientifically correct or that undeclared dependencies were unchanged.