cprog
English | 한국어
cprog is a thin wrapper around the system cp. It overlays a per-file progress bar only in a Linux interactive terminal (the progress feature is Linux-only, needing /proc); anywhere a footer would not be safe — a pipe, a redirect, CI, non-Linux, a background job — it behaves transparently, byte-for-byte identical to cp. It runs the real cp and draws a two-row footer only for files that take a while, erasing it when done. cp -v output is relayed only if you asked for -v; otherwise cprog stays as quiet as cp and names the file in the footer instead. No external progress command, no hidden PTY, no screen-scraping.
…/backup/archives/dataset.tar.zst
████████████░░░░░░░░ 62.33 % 0.9/1.4 GiB (142 MiB/s) ⏳ 00:05What it is
- The real copy is done by cp, and its semantics are untouched. cp's exit code is the final
authority.
- In managed mode it injects and captures -v for its timing — but relays it to the terminal
only when you passed -v yourself. Without it cprog prints nothing cp would not have printed. When a single file gets slow, it locates that file via /proc/<pid/fd and reads the growing size with stat to draw its own progress bar, naming the file on the row above.
- Where a footer isn't safe it falls back to passthrough — streams inherited, environment
untouched, byte-identical to cp. That covers: stdout or stderr not a TTY (a pipe or a redirect), the two not on the same terminal, TERM unset or dumb, CI set, non-Linux, stdbuf missing, a background job (cprog … &), an interactive flag (-i), --help/--version, and CPROGPASSTHROUGH set — an explicit escape hatch that also makes cprog exec the real cp in place, leaving no wrapper process at all.
It computes progress itself from cp's own -v timing and the kernel's /proc/stat — no external progress tool, no hidden PTY, no screen-scraping.
Escape hatch
Set CPROGPASSTHROUGH (any value) and cprog gets out of the way entirely: passthrough is forced over every other condition, nothing is added — not even the --version line — and cprog execs the real cp in place, so $!, signals and exit codes are cp's own, with no wrapper process left.
CPROG_PASSTHROUGH=1 cp -r photos backup # this one copy, exactly plain cp
export CPROG_PASSTHROUGH=1 # this whole shell (unset to restore)To bypass cprog altogether there is always \cp (or command cp), which skips the alias.
Why cprog — vs. the alternatives
"Show cp's progress" already has answers. The question is: is it still the real cp, and what does the progress cost you?