#!/usr/bin/env zsh emulate -L zsh export LC_ALL=C AUDIT="$HOME/msd512-audit" LEDGER="$AUDIT/ledger.tsv" SM="$AUDIT/src.manifest.tsv" src_total=$(wc -l < "$SM" | tr -d ' ') awk -F'\t' '{c[$1]++} END{for(k in c) printf "%s\t%d\n", k, c[k]}' "$LEDGER" | sort > "$AUDIT/status.counts.tsv" acct=$(awk -F'\t' '{print $4}' "$LEDGER" | sort -u | wc -l | tr -d ' ') cut -f4 "$LEDGER" | sort -u > "$AUDIT/accounted.txt" cut -f3 "$SM" | sort -u > "$AUDIT/all.src.txt" comm -23 "$AUDIT/all.src.txt" "$AUDIT/accounted.txt" > "$AUDIT/unaccounted.tsv" # integrity spot check: re-hash 1% of migrated files at DST HN=$(cat "$AUDIT/hash.algo") case "$HN" in blake3) HASH=(b3sum);; xxh128) HASH=(xxh128sum);; *) HASH=(shasum -a 256);; esac awk -F'\t' '$1=="MIGRATED"{print $2"\t"$5}' "$LEDGER" | awk 'NR%100==1' > "$AUDIT/spot.list" bad=0; n=0 while IFS=$'\t' read -r h p; do n=$(( n + 1 )) a=$("${HASH[@]}" < "$p" 2>/dev/null | awk '{print $1}') [[ "$a" == "$h" ]] || { bad=$(( bad + 1 )); print "SPOTFAIL\t$p" >> "$AUDIT/spot.fail.tsv"; } done < "$AUDIT/spot.list" # delete candidates: SRC files with a verified DST twin (REVIEW ONLY, never executed) awk -F'\t' '$1=="MIGRATED"||$1=="DEDUP"{printf "%s\t%s\t%s\n", $4, $5, $2}' "$LEDGER" > "$AUDIT/delete-candidates.tsv" print "===== PHASE4 =====" printf 'src files=%d accounted=%d unaccounted=%d\n' $src_total $acct "$(wc -l < "$AUDIT/unaccounted.tsv" | tr -d ' ')" cat "$AUDIT/status.counts.tsv" printf 'spot-check: %d re-hashed, %d mismatches\n' $n $bad awk -F'\t' '$1=="MIGRATED"{b+=$3} END{printf "migrated bytes: %.1f GiB\n", b/1073741824}' "$LEDGER" printf 'delete-candidates: %s files (REVIEW ONLY)\n' "$(wc -l < "$AUDIT/delete-candidates.tsv" | tr -d ' ')" head -5 "$AUDIT/unaccounted.tsv"