Skip to content

0.11.0

Latest

Choose a tag to compare

@github-actions github-actions released this 31 Aug 20:36
· 6 commits to main since this release
Immutable release. Only release title and notes can be modified.

Rust Coreutils 0.11.0 Release:

We are happy to announce the release of Rust Coreutils 0.11.0 - a release focused on error messages, performance and GNU compatibility.
The big change is a new diagnostic engine built on ariadne. When a chmod mode, a cut list, a sort key or a tr set fails to parse, we now echo the arguments back with a caret under the character at fault, like a compiler does. See our blog post for more information: https://uutils.org/blog/2026-08-error-diagnostics/

Example with cut:
image

or test:
image

PGO release builds are enabled for Linux, macOS and Windows (up to 31% faster), and a lot of per-utility optimization work landed on top of that. We also now treat a utility being significantly slower than GNU as a bug.

We continued to improve the GNU compatibility and we are now at 653 passing, 22 failing, 0 errors.


GNU Test Suite Compatibility:

Result 0.10.0 0.11.0 Change 0.10.0 to 0.11.0 % Total 0.10.0 % Total 0.11.0 % Change 0.10.0 to 0.11.0
Pass 645 653 +8 94.44% 95.33% +0.89%
Skip 9 10 +1 1.32% 1.46% +0.14%
Fail 28 22 -6 4.10% 3.21% -0.89%
Error 1 0 -1 0.15% 0% -0.15%
Total 683 685 +2 (new tests)

Note: 653 passing and 23 failing are both records for us, and this is the first release with no erroring test. Note that the suite grew by 2 tests this cycle (local backport). We also list the tests excluded from the pass/fail percentages now.


GNU testsuite evolution


Highlights:

  • Modern Error Diagnostics (new)

    • A new diagnostic engine based on ariadne. When stderr is a terminal, a parse error is printed as a report: the arguments are echoed back as a source line, a caret marks the culprit and a help line explains the syntax. See the blog post for before/after examples
    • Carets landed in chmod, mkdir, mkfifo, mknod, install, tr, expr, sort, numfmt, cut, env, head, tail, truncate, split, shred, stdbuf, od, seq, dd, stat, join, csplit, ls, df and du
    • A caret can point inside a quoted argument and at a single character. The reports are localized (format, checksum and advice strings) and still print the usual Try '... --help' hint. A label is only added when it says something useful
    • UUTILS_DIAG controls the behavior, and the caret rendering can be compiled out for size-constrained builds
    • Diagnostics are written in a single stderr call, so concurrent writers cannot interleave them
  • Performance

    • PGO (profile-guided optimization) release builds: up to 31% faster - now enabled for the published Linux, macOS and Windows artifacts too.
    • cp: opens the file only once (+32.93%) and reuses the already-open destination fd when a reflink clone falls back
    • join: 1.37x faster on paired input, 2.5x faster than GNU, by skipping the locale comparison when it cannot change the result
    • od --skip-bytes uses splice(2) on non-seekable input; tac uses fast_copy; dd no longer faults in the whole copy buffer before reading and page-aligns its read buffer
    • Fewer allocations and syscalls in ptx (+4% via fxhash, plus fewer per-word allocations), nl (hoisted per-line prefix), tail (no double allocation per reverse chunk, no stat), expand/unexpand (no stat/is_dir), numfmt and sort
    • New benchmarks for ptx, basenc and the numfmt stdin path
    • A utility being significantly slower than GNU is now considered a bug - please report it as one
  • GNU Compatibility

    • 653 passing GNU tests (+8), 23 failures (-6) and no erroring test
    • New GNU-matching options: uname -A/--all-labeled, cut -F and --whitespace-delimited, pr --columns/--join-lines/-f alias and an optional argument for -n
    • Behavior fixes in pr (page length of exactly 10, columns that do not divide evenly, -e at the end of a cluster), numfmt (leading +, scientific notation), uniq/truncate/paste (a repeated option overrides the earlier one), join -o accumulating fields, id group ordering, unexpand/expand tab-list separators, mkdir EEXIST, more -f/-l, fold widths, sort -t=, stat nanosecond timestamps and Block size, od 16 significant digits, date trailing timezones
    • A new gnu/usage_vs_refs.sh check verifies that every option we document also appears in GNU's texi docs
    • More error messages carry the real OS text instead of a stripped or made up one (rm, env, od, chroot, stdbuf, tee, cut, date, tsort, pathchk, sort)
  • Security Hardening

    • mv/cp: xattr TOCTOU fixed by moving to file-descriptor-based operations
    • rm: no longer follows a symlink swapped in at the -r operand
    • chmod: uses fchmodat for recursive mode changes and no longer follows in-tree symlinks with -R --reference
    • cp: does not chmod through the destination symlink; mv does not put a symlink in its target's hardlink group
    • stdbuf: fixed a temporary-directory leak
  • Robustness: Anti-Panic & Anti-Hang

    • Hangs fixed: split endless loop, yes deadlock, sort Lines fuse when a chunk boundary lands exactly at EOF
    • Panics and aborts fixed in stat and csplit on /dev/full, ls with an invalid QUOTING_STYLE on unwritable stderr, od on large ASCII dump widths, printf on large numeric and %s/%c field widths, nl with -w i32::MAX (rejection plus a 32-bit OOM fix), pr and csplit integer overflow, dd u64 wraparound, touch leap-second year overflow, tail -c +N past the seek limit, tac SIGBUS on a truncated mmap, who -q stdout write errors
    • uucore::parse_size no longer overflows on a large % size
  • Cross-platform Reach

    • Windows: kill and uptime implementations, and test -ef, -t, -h/-L, -r, -w, -x
    • WASI: touch timestamps, cp symlinks, expr, cleaned-up core platform abstractions and cat integration coverage
    • df got a fallback statfs path using the mount table; uptime dropped its /proc dependency on more targets; stty and chgrp are now gated by target support; better iOS and Fuchsia handling
  • Dependency Diet

    • Dropped byteorder, same-file, filetime, winapi-util, file_diff, mockstream, binary-heap-plus, compare, arrayref, exacl and dns-lookup in favor of std, rustix and windows-sys
  • Internationalization

    • Symbolic mode parsing errors, the chmod --verbose messages and the new diagnostic strings are now translatable
    • ls sorts names using locale-aware collation, comm compares lines with the locale collation, nl supports multibyte one-character section delimiters and cut handles multibyte fields, bytes and delimiters correctly
    • uucore rebuilds its embedded locales when the consumer's dependencies change
  • Contributions: This release landed 358 pull requests from 26 new contributors. We also passed 1000 people having contributed to uutils coreutils. Per our activity tracking, August 2026 was our busiest month so far, with 476 commits from 57 authors


Call to Action:

Try it in your browser - Online Playground powered by WebAssembly
Help us translate - Contribute to Rust Coreutils on Weblate
Sponsor us on GitHub to accelerate development: github.com/sponsors/uutils

What's Changed

base32

basename

  • basename: simplify handling missing operand by @oech3 in #14202

basenc

cat

chmod

  • chmod: only report umask-curtailed modes for option-like operands by @dhruv-15-03 in #13731
  • chmod: don't follow in-tree symlinks with -R --reference by @Angadi56 in #13842
  • chmod: translate chmod-verbose-neither-changed much more by @oech3 in #13872
  • chmod: use the libc fchmodat symbol for recursive mode changes by @sylvestre in #14121
  • chmod: remove duplicate code handling symlinks by @cakebaker in #13873
  • chmod: simplify a nested match by @Devel08 in #14234

chroot

cksum

comm

cp

csplit

  • csplit: avoid negate-with-overflow on an i32::MIN regex line offset by @leeewee in #13753
  • csplit: don't panic on /dev/full stdout by @Devel08 in #14130

cut

date

  • date: strip errno when write to stdout fails by @Devel08 in #14206
  • date: update parse_datetime to 0.16.0 to accept \v and \f as whitespace by @wtcpython in #14221
  • date: reject a trailing timezone when the input already has one by @ARMeeru in #14168

dd

df

dircolors

dirname

  • dirname: simplify handling missing operand by @oech3 in #14203

env

  • env: extract error message from OS instead of showing unknown error by @oech3 in #13960
  • env: avoid accessing by index & simplify loop by @oech3 in #14107

expand

expr

fmt

fold

hashsum

  • *sum: hide the legacy --text from document by @oech3 in #14131

head

hostname

id

  • id: order groups= by effective gid and -G by real gid, like GNU by @sylvestre in #14103

install

  • install: allow non-directory special files as targets by @MsfPablo in #13791
  • install: strip "(os error N)" from --strip-program failure by @MsfPablo in #13914
  • install: remove filetime from dep by @oech3 in #13947
  • install, comm: remove file_diff in favor of uucore::fs::are_files_identical by @wtcpython in #14113
  • test_install.rs: test for ficlone (reflink) by @oech3 in #13580
  • install: reduce nest by if & match by @oech3 in #13346
  • install: remove a to_string_lossy by @oech3 in #13338
  • tests_install.rs: replace filetime by std by @oech3 in #14172

join

kill

ln

  • hard link creation failure has src and dst swapped in error message by @Devel08 in #13745
  • ln: swap dest & source in french locale by @Devel08 in #13905
  • ln: remove pub to improve the public API by @oech3 in #14225
  • ln: avoid accessing by index & simplify if by @oech3 in #14197
  • ln: clarify exclusive pattern by @oech3 in #14266

ls

mkdir

  • mkdir: return a proper error mesage when dir is inexistent by @Devel08 in #13836
  • strip errno when argument is not a directory but an existing file by @Devel08 in #13890
  • mkdir: do not ignore EEXIST on non-recursive creation by @alexchen-sys in #13986

mkfifo

  • mkfifo: use std::io::Result, remove manual conversion by @oech3 in #13777
  • mkfifo: fix mismatched types error on freebsd by @xtqqczze in #14259

mktemp

  • mktemp: remove the temp file when its name cannot be printed by @sylvestre in #13853

more

mv

  • mv: use GNU default error when overwriting non-empty directory by @aaron-ang in #10078
  • tests_mv.rs: replace filetime by std by @oech3 in #13948
  • mv: don't put a symlink in its target's hardlink group by @sylvestre in #14170

nl

numfmt

od

pathchk

  • pathchk: readable error message without scrolling terminal by @oech3 in #13220
  • pathchk: reject missing operand by clap by @oech3 in #14147
  • pathchk: prepend pathchk: to error message & improve error for long name by @oech3 in #14146

pinky

  • pinky: make tests resilient to the idle column changing between runs by @sylvestre in #14155

pr

printf

ptx

readlink

  • readlink: reject missing operand by clap by @oech3 in #14151

rm

  • rm: replace a hardcoded error message by @oech3 in #13956
  • rm: extract permission denied message from OS by @oech3 in #13967
  • rm: do not follow a symlink swapped in at the -r operand by @sylvestre in #14122

sleep

sort

split

stat

stdbuf

tac

tail

tee

  • tee: show_err instead of writing directly in stderr and strip error by @Devel08 in #14125
  • tee: align error message with GNU by @oech3 in #14134

test

touch

tr

true

  • false, true: use show_err instead of writing to stderr by @Devel08 in #14193

truncate

tsort

uname

  • uname: add -A/--all-labeled, following GNU master by @sylvestre in #13912
  • uname: move label separators into locale strings for -A/--all-labeled by @sylvestre in #13954

unexpand

uniq

uptime

who

yes

Error Diagnostics

Performance (PGO)

Security

  • mv,cp: fix xattr TOCTOU by using file descriptor-based operations by @sylvestre in #10545

uucore

  • uucore: fix parse_size overflow on a large % size by @MsfPablo in #13742
  • uucore: fix clippy::match_same_arms without => _, by @oech3 in #13831
  • uucore::pipes: simplify by @oech3 in #13858
  • uucore::pipes::drain_pipe: catch 2nd+ splice's error by @oech3 in #13859
  • encoding.rs: simplify many match by @oech3 in #14096
  • validate.rs: simplify errors by @oech3 in #14099
  • uucore, cat: remove winapi-util dependency in favor of windows-sys and std by @wtcpython in #14110
  • validate.rs: extract actual error message from OS by @oech3 in #14098
  • uucore: rebuild embedded locales when the consumer's dependencies change by @sylvestre in #14233
  • fsext: do not confuse f_bsize with f_frsize on Linux by @Socialpranker in #14192

Testing

Code Quality & Cleanup

CI & Build

  • publish.sh: adjust to the new API by @sylvestre in #13761
  • fetch-gnu.sh: remove unnecessary 2 spaces by @oech3 in #13792
  • ci: trust preinstalled Homebrew taps on macOS by @xtqqczze in #13782
  • uucore/Cargo.toml: don't guard openssl by unix by @oech3 in #13824
  • fix cspell by @oech3 in #13861
  • fetch-gnu.sh: remove incorrect exit 0 (pass tests/cat/splice) by @oech3 in #13860
  • Revert "ci: trust preinstalled Homebrew taps on macOS" by @xtqqczze in #13875
  • Update automake download URL and add checksum verification by @sylvestre in #13922
  • ci: add copilot-code-review.yml to declare a runner for Copilot code review by @sylvestre in #13942
  • gnu: list the tests excluded from the pass/fail percentages by @sylvestre in #13891
  • Add empty-backup-suffix.sh to backport list by @sylvestre in #13973
  • add misc/getopt_vs_usage.sh to the GNU unfixable tests by @sylvestre in #13979
  • wasm: add expr & test to feat_wasm by @sylvestre in #13981
  • gnu/usage_vs_refs.sh checks that all options appear in GNU's texi docs. by @sylvestre in #13997
  • Cargo.toml: move 3 utils to feat_Tier1 by @oech3 in #14027
  • GnuTests: remove LD_PRELOAD from dd/fail-ftruncate-fstat by @oech3 in #14053
  • CI: pin the GNU test comparison to the latest main reference run by @sylvestre in #14112
  • ci: add check for empty output assertions by @cakebaker in #14116
  • CI: don't use the lagging server-side status filter by @sylvestre in #14137
  • build cygwin cksum with openssl on the CI by @oech3 in #14079
  • CI: remove unnecessary rust-toolchain by @oech3 in #14142
  • ci: fix benchmarks workflow to only run on changed crates by @BipulLamsal in #14124
  • try to fix publishing tag/latest-commit by @oech3 in #14143
  • GnuTests: fix hardcoded pathes to GNU executables by @oech3 in #14190
  • build: use "selinux" instead of "feat_selinux" feature name by @xtqqczze in #12431

Documentation

Platform Support

Dependency Updates

  • chore(deps): update rust crate blake3 to v1.8.6 by @renovate[bot] in #13765
  • chore(deps): update rust crate clap_mangen to v0.3.1 by @renovate[bot] in #13759
  • build(deps): update rust crates by @xtqqczze in #13763
  • chore(deps): update rust crate clap_mangen to v0.3.2 by @renovate[bot] in #13783
  • chore(deps): update rust crate clap_complete to v4.6.9 by @renovate[bot] in #13781
  • chore(deps): update rust crate thiserror to v2.0.20 by @renovate[bot] in #13807
  • chore(deps): update endbug/add-and-commit action to v11 by @renovate[bot] in #13817
  • chore(deps): update rust crate ctor to v1.0.13 by @renovate[bot] in #13838
  • chore(deps): update rust crate bstr to v1.13.1 by @renovate[bot] in #13846
  • chore(deps): update rust crate clap_mangen to v0.3.3 by @renovate[bot] in #13904
  • chore(deps): update rust crate icu_datetime to v2.3.0 by @renovate[bot] in #13940
  • chore(deps): update rust crate icu_collator to v2.3.0 by @renovate[bot] in #13944
  • chore(deps): update dawidd6/action-download-artifact action to v22 by @renovate[bot] in #13961
  • chore(deps): update dawidd6/action-download-artifact action to v23 by @renovate[bot] in #13963
  • chore(deps): update rust crate cc to v1.4.3 by @xtqqczze in #13971
  • chore(deps): update rust crate similar to v3.2.0 by @renovate[bot] in #13984
  • chore(deps): update rust crate blake2b_simd to v1.0.5 by @renovate[bot] in #14035
  • chore(deps): update rust crate blake3 to v1.8.7 by @renovate[bot] in #14036
  • fix(deps): refactor RustCrypto crates package configuration by @xtqqczze in #14037
  • Cargo.lock: remove arrayref by @cakebaker in #14041
  • chore(deps): update rust crate icu_locale to v2.3.1 by @renovate[bot] in #14055
  • chore(deps): update rust crate icu_collator to v2.3.1 by @renovate[bot] in #14054
  • chore(deps): update rust crate icu_provider to v2.3.1 by @renovate[bot] in #13941
  • chore(deps): update dawidd6/action-download-artifact action to v24 by @renovate[bot] in #14061
  • Cargo.toml: remove unused exacl workspace dependency by @wtcpython in #14089
  • chore(deps): update rust crate dns-lookup to v4 by @renovate[bot] in #14194

Version Management

New Contributors

Full Changelog: 0.10.0...0.11.0