← All one-liners·#079·data·self contained·beginner

Turn a shell loop into a JSON array with jo, jq's inverse

jq is unbeatable for tearing JSON apart; jo is the boring, forgotten tool for building it back up. Each `jo key=value ...` call emits one type-aware JSON object (numbers and booleans auto-detected, no manual quoting), so a plain shell for-loop becomes a stream of JSON records ready to slurp, sort, and filter with jq — no printf/sed JSON-escaping gymnastics.

Setup
  • → apt install jo # or: brew install jo
Cost per run
free
The one-liner
$ for f in *; do [ -f "$f" ] && jo name="$f" bytes=$(stat -c%s "$f"); done | jq -s '.' | jq 'sort_by(-.bytes) | .[0:5]'
What each stage does
  1. [01] jofor f in *; do [ -f "$f" ] && jo name="$f" bytes=$(stat -c%s "$f"); done
    Loop the current directory's entries and emit one compact JSON object per regular file — `bytes=$(stat -c%s "$f")` is auto-detected as a JSON number, not a quoted string, with zero manual escaping.
  2. [02] jqjq -s '.'
    Slurp the newline-delimited stream of single objects into one JSON array — the hand-off point from shell-native construction to normal jq querying.
  3. [03] jqjq 'sort_by(-.bytes) | .[0:5]'
    Rank by size descending and keep the top 5 — the same array can just as easily be grouped, filtered, or POSTed to an API as a JSON body.
Expected output (sample)
[
  {
    "name": "README.md",
    "bytes": 10537
  },
  {
    "name": "deno.json",
    "bytes": 1629
  },
  {
    "name": "vite.config.ts",
    "bytes": 854
  },
  {
    "name": "playwright.config.ts",
    "bytes": 808
  },
  {
    "name": "main.ts",
    "bytes": 416
  }
]
Caveats & tips
  • Verified on jo 1.9 (apt, Debian/Ubuntu package), run for real against oneliner101/'s own top-level *.json/*.ts/*.md files — output above is the real, unmodified stdout.
  • This apt build auto-detects numbers/booleans from bare `key=value` (no `:=` operator support) — `count=5` is already a JSON number; check `jo --help`/`jo -v` on your platform since jpmens/jo upstream and distro packages have drifted.
  • The same `jo ... | curl -d @- ...` shape replaces here-doc JSON bodies for webhook/API POSTs built from shell variables — the loop above is one instance of a more general pattern.
  • For deeply nested output, `jo -p` pretty-prints and `jo -a` wraps args directly into an array without the jq -s slurp step.