You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-q is documented as "print only errors and a one-line summary", and it is the mode the shipped systemd/[email protected] runs (ExecStart=/usr/bin/oans --quiet --hashfile=..., commented "keeps the journal to a short summary"). In practice it does close to the opposite: it keeps per-pass noise and suppresses the summary.
1. Report mode prints two lines per generation pass.
print_dupes_table() in src/run_dedupe.c emits its "Simple read and compare of file data found %u instances of %s" header before the if (quiet || res->num_dupes == 0) return; guard a few lines below. It's called once per pass per kind, so a multi-generation scan prints 2×N lines — including ones reporting zero:
$ oans -rq --hashfile=/tmp/h.db ~/gitSimple read and compare of file data found 1513 instances of files that might benefit from deduplication.Simple read and compare of file data found 2 instances of extents that might benefit from deduplication.Simple read and compare of file data found 2864 instances of files that might benefit from deduplication.Simple read and compare of file data found 5 instances of extents that might benefit from deduplication.Simple read and compare of file data found 342 instances of files that might benefit from deduplication.Simple read and compare of file data found 15 instances of extents that might benefit from deduplication.
Six lines, none of which is a summary, and the counts are per-pass so they don't even sum to anything a user would want.
2. The real summary is suppressed by -q — including the failure line.
run_dedupe.c:~1176 gates the whole Summary block on if (!quiet). That block is the only place Reclaimed, Not deduped … N changed since scan, N failed, and Already shared are ever printed. So the quiet mode used by the unattended timer is precisely the mode that hides the dedupe failure counters.
3. The one line -q does print in dedupe mode is the wrong number.
Three 5 MB copies, of which two are reclaimable:
$ oans -rdq --hashfile=/tmp/h.db /scratch/qprobeComparison of extent info shows a net change in shared extents of: 15000000
Non-quiet mode reports Reclaimed 9.5 MiB for the same run. The quiet line is the fiemap diagnostic, which counts the surviving copy too (≈2× for pairs, 3× here) — a known quirk, already documented in CLAUDE.md, but -q is exactly where scripts and journals read it. It's also raw bytes with no unit. Someone logging quiet output weekly is recording a number ~1.5–2× the space actually freed.
Proposed solution
Make -q mean what it says.
Move the printf in print_dupes_table() below the quiet guard so the per-pass header is suppressed like the table it heads. One-line fix.
Print the Summary block under -q, either in full or condensed to a genuine one-liner, e.g. oans: reclaimed 9.5 MiB across 3 groups in 1.2s
Report Reclaimed, not the fiemap delta, as the quiet one-liner, formatted with human_size() like everywhere else. If the fiemap delta is worth keeping as a diagnostic, it belongs behind -v, not in the mode designed for logs.
Worth deciding together: whether -q should stay a human one-liner given --progress=json and --json already serve machines. I think yes — the journal is read by humans — but that argues for the condensed form above rather than the full multi-line block.
Alternatives considered
Point users at --progress=json. Different job: it's a stderr JSONL progress stream for a live UI, not an end-of-run summary, and it doesn't cover the scan-side skips at all.
Point users at --json. Reports on the hashfile, in a separate invocation, and adds a jq dependency for what should be one readable journal line.
Change the systemd unit to drop --quiet. Makes the journal much noisier for every user and leaves -q broken for everyone driving oans from a script.
Leave the fiemap number and document it. It's already documented in CLAUDE.md and it's still the wrong figure to hand an unattended logger; the honest Reclaimed value exists and is already computed.
What problem would this solve?
-qis documented as "print only errors and a one-line summary", and it is the mode the shippedsystemd/[email protected]runs (ExecStart=/usr/bin/oans --quiet --hashfile=..., commented "keeps the journal to a short summary"). In practice it does close to the opposite: it keeps per-pass noise and suppresses the summary.1. Report mode prints two lines per generation pass.
print_dupes_table()insrc/run_dedupe.cemits its"Simple read and compare of file data found %u instances of %s"header before theif (quiet || res->num_dupes == 0) return;guard a few lines below. It's called once per pass per kind, so a multi-generation scan prints 2×N lines — including ones reporting zero:Six lines, none of which is a summary, and the counts are per-pass so they don't even sum to anything a user would want.
2. The real summary is suppressed by
-q— including the failure line.run_dedupe.c:~1176gates the wholeSummaryblock onif (!quiet). That block is the only placeReclaimed,Not deduped … N changed since scan, N failed, andAlready sharedare ever printed. So the quiet mode used by the unattended timer is precisely the mode that hides the dedupe failure counters.3. The one line
-qdoes print in dedupe mode is the wrong number.Three 5 MB copies, of which two are reclaimable:
Non-quiet mode reports
Reclaimed 9.5 MiBfor the same run. The quiet line is the fiemap diagnostic, which counts the surviving copy too (≈2× for pairs, 3× here) — a known quirk, already documented inCLAUDE.md, but-qis exactly where scripts and journals read it. It's also raw bytes with no unit. Someone logging quiet output weekly is recording a number ~1.5–2× the space actually freed.Proposed solution
Make
-qmean what it says.printfinprint_dupes_table()below thequietguard so the per-pass header is suppressed like the table it heads. One-line fix.Summaryblock under-q, either in full or condensed to a genuine one-liner, e.g.oans: reclaimed 9.5 MiB across 3 groups in 1.2s-q—Not deduped … N failedand the scan-side skip counts from Scan-phase skips and errors are never counted, reported, or exported #145 are "errors", which quiet's own contract promises to keep.Reclaimed, not the fiemap delta, as the quiet one-liner, formatted withhuman_size()like everywhere else. If the fiemap delta is worth keeping as a diagnostic, it belongs behind-v, not in the mode designed for logs.Worth deciding together: whether
-qshould stay a human one-liner given--progress=jsonand--jsonalready serve machines. I think yes — the journal is read by humans — but that argues for the condensed form above rather than the full multi-line block.Alternatives considered
--progress=json. Different job: it's a stderr JSONL progress stream for a live UI, not an end-of-run summary, and it doesn't cover the scan-side skips at all.--json. Reports on the hashfile, in a separate invocation, and adds ajqdependency for what should be one readable journal line.--quiet. Makes the journal much noisier for every user and leaves-qbroken for everyone driving oans from a script.CLAUDE.mdand it's still the wrong figure to hand an unattended logger; the honestReclaimedvalue exists and is already computed.