cloverleaf-larry/lib/each-site.sh
Bryan Johnson 3eb88f86c8 v0.4.1: each / each-site / len2nl / csv-to-table / table-to-csv
Five small Unix-style loop & format helpers, fully offline:

lib/each.sh
  - replaces v1 `each`
  - run a CMD per item: args, stdin lines, or {}-placeholder substitution
  - example: tbn adt | awk '{print $2}' | each.sh 'route_test {}'

lib/each-site.sh
  - replaces v1 each_site / each_site_hdr / each_site_tcl patterns
  - iterates every site under $HCIROOT with HCISITE/HCISITEDIR auto-exported
  - --filter REGEX limits which sites; --hdr prints a header before each

lib/len2nl.sh
  - replaces v1 `len2nl`
  - strict superset: handles length-prefixed (digits before MSH),
    MLLP (\x0b...\x1c\x0d), and segment CRs (→ LF)
  - works as stdin filter or with file arg

lib/csv-to-table.sh
  - 2-column CSV → Cloverleaf .tbl format
  - emits proper prologue (who, date, bidir, type, version)
  - --has-header --default VALUE --bidir 0|1 --in-delim CHAR --user NAME --out PATH

lib/table-to-csv.sh
  - reverse: .tbl → CSV
  - --with-header --delim CHAR --include-meta
  - confirmed clean round-trip: CSV → table → CSV byte-identical for the data rows

All 5 are pipeable, have --help, zero external deps beyond bash+awk+sed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:05:19 -07:00

55 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# each-site.sh — run a command for each site under $HCIROOT.
# Replaces v1 `each_site` / `each_site_hdr` / `each_site_tcl` patterns.
#
# Usage:
# each-site.sh [--hciroot DIR] [--hdr] [--filter REGEX] <CMD ...>
#
# The current site is exposed to CMD as the env vars HCISITE and HCISITEDIR.
# The literal token {} in CMD, if present, is replaced with the site name.
#
# Examples:
# each-site.sh 'lib/nc-find.sh --name adt --netconfigs "$HCISITEDIR/NetConfig"'
# each-site.sh --hdr 'echo "Hey from $HCISITE; netconfig=$HCISITEDIR/NetConfig"'
# each-site.sh --filter '^(ancout|epic)$' 'wc -l "$HCISITEDIR/NetConfig"'
# each-site.sh 'lib/nc-parse.sh list-protocols "$HCISITEDIR/NetConfig" | wc -l'
#
# --hdr prints a "===== <site> =====" header before each run.
set -o pipefail
HCIROOT_OVR=""
HEADER=0
FILTER=""
while [ $# -gt 0 ]; do
case "$1" in
--hciroot) shift; HCIROOT_OVR="$1" ;;
--hdr) HEADER=1 ;;
--filter) shift; FILTER="$1" ;;
-h|--help) sed -n '2,18p' "$0"; exit 0 ;;
--) shift; break ;;
-*) echo "each-site: unknown flag: $1" >&2; exit 2 ;;
*) break ;;
esac
shift
done
[ $# -ge 1 ] || { echo "each-site: needs a CMD" >&2; exit 2; }
CMD="$*"
ROOT="${HCIROOT_OVR:-${HCIROOT:-}}"
[ -n "$ROOT" ] && [ -d "$ROOT" ] || { echo "each-site: no \$HCIROOT (or --hciroot)" >&2; exit 2; }
# Site = subdir of ROOT that contains a NetConfig file.
SITES=$(find "$ROOT" -mindepth 1 -maxdepth 2 -name NetConfig -type f 2>/dev/null \
| xargs -I{} dirname {} 2>/dev/null \
| xargs -I{} basename {} 2>/dev/null \
| sort -u)
[ -n "$SITES" ] || { echo "each-site: no sites with NetConfig under $ROOT" >&2; exit 1; }
while IFS= read -r site; do
[ -z "$site" ] && continue
if [ -n "$FILTER" ] && ! printf '%s' "$site" | grep -Eq -- "$FILTER"; then continue; fi
[ "$HEADER" = "1" ] && printf '\n===== %s =====\n' "$site"
HCISITE="$site" HCISITEDIR="$ROOT/$site" eval "${CMD//\{\}/$site}"
done <<< "$SITES"