xargs GNU vs BSD: Portable Pipelines
GNU xargs on Linux and BSD xargs on macOS accept different flags and differ on empty input, so portable scripts stick to the common subset.
Mixed CI fleets run Linux and macOS runners. The two xargs implementations diverge on a handful of flags, and knowing them keeps a pipeline green on both.
What it does
GNU xargs (Linux, util findutils) and BSD xargs (macOS) share -0, -n, -I, -P, and -t, but differ elsewhere. GNU implies --no-run-if-empty by default and offers -d and -a; BSD already skips empty input but lacks -d and -a, and older BSD does not accept the long --no-run-if-empty spelling.
Common usage
# portable: only common flags
find . -name '*.o' -print0 | xargs -0 -n 50 rm -f
# Linux-only flags to avoid in portable scripts
xargs -d ',' ... # GNU only
xargs -a file ... # GNU onlyDifferences
| Behavior | GNU (Linux) | BSD (macOS) |
|---|---|---|
| Empty input | Skips command (implies -r) | Also skips command |
| -r / --no-run-if-empty | Both spellings work | Short -r often accepted; long form may not |
| -d delimiter | Supported | Not supported |
| -a file | Supported | Not supported (use < file) |
| -0, -n, -I, -P, -t | Supported | Supported |
In CI
Stick to -0, -n, -I, -P, and -t for pipelines that must run on both Linux and macOS runners. Replace -d with "tr <delim> '\0' | xargs -0" and replace -a with "xargs ... < file". On Linux you can install GNU findutils inside a macOS job (gxargs) if you truly need GNU-only flags.
Common errors in CI
On macOS, GNU-only flags fail with "xargs: illegal option -- d" or "-- a". The same script that runs on the Linux runner breaks on the macOS runner over these. The empty-input default rarely differs in practice today, but writing -r explicitly is harmless and documents intent across both.