SysadminNews

Rust Coreutils 0.10 Clears 93 Percent of the GNU Tests

On this page
  1. The panics had to go
  2. Actual new options, briefly
  3. The gap between this and your machine
  4. What we would do
  5. Sources and further reading

Rust Coreutils 0.10 was released on August 5, and the number that tells the story is 645 passing GNU test suite cases against 29 failures, up from 625 in version 0.9. That moves the pass rate from 90.58 percent to 93.48 percent, an all time high for the project. The rest of the release is the kind of work a drop in replacement has to do before anyone trusts it: an anti panic campaign across more than twenty utilities, races between checking and acting on a path closed off, SELinux labels applied at creation time, and a handful of genuinely new options including mv --exchange for atomically swapping two paths.

The short answer

Rust Coreutils 0.10 landed on August 5 with the project's highest GNU compatibility to date and a release focused almost entirely on being trustworthy rather than novel. Races between checking and acting on a path were closed, SELinux labels are now applied when mkdir, mkfifo and mknod create something rather than after, and panics were removed from more than twenty utilities including sort, chmod and install. New options include mv --exchange for atomic swaps, rm --one-file-system and install --reflink. A wasm32-wasip2 target was added and Windows support widened.

93.48%of the GNU test suite passing, up from 90.58 percent in 0.9
645 / 29tests passing against failing, 27 fewer failures than before
20+utilities cleared of panics and aborts this cycle
Answer card: Rust Coreutils 0.10 was released on August 5 2026 with 645 GNU test suite cases passing against 29 failures, a pass rate of 93.48 percent up from 90.58 percent in version 0.9, an anti panic campaign across more than twenty utilities, new options including mv --exchange and rm --one-file-system, and a new wasm32-wasip2 build target.
Rust Coreutils 0.10 at a glance. Sources: the uutils 0.10.0 release notes on GitHub and Phoronix reporting, August 5, 2026. PNG

There is a specific kind of release that means a project has stopped trying to impress you and started trying to be relied upon. Rust Coreutils 0.10, out on August 5, is one of those. Almost nothing in it is a feature. Most of it is the removal of reasons not to use it.

The measurement the project reports against is the GNU coreutils test suite, and 0.10 passes 645 cases against 29 failures. Version 0.9 passed 625. Twenty seven fewer failures moves the rate from 90.58 percent to 93.48, described as an all time high. What sits behind that number is mundane and specific: nproc behaving correctly under different CPU conditions, date handling years outside the ordinary range, formatting differences nobody notices until a script depends on one.

The panics had to go

The most important entry in the changelog does not appear in the headline.

Rust's failure mode of last resort is a panic: the program aborts, prints a message about a thread panicking, and exits in a way no shell script anticipates. That is acceptable in a prototype and unacceptable in sort. The classic Unix contract is narrow and everyone builds on it: do the work, or fail with a documented exit code and a message on standard error. A panic honours neither part, and a pipeline that receives one has no idea what to do.

Version 0.10 went through more than twenty utilities removing panics and aborts, sort, chmod and install among them, replacing them with real error handling. You cannot demonstrate this work in a screenshot. It is the difference between a tool people try and a tool people put in a cron job.

The same release closed off races between checking a path and acting on it, and changed mkdir, mkfifo and mknod so SELinux labels are applied at creation rather than applied afterwards. Applying a label after the fact leaves a moment where the object exists unlabelled, and on a system where the label is the policy, that moment is a correctness problem.

Terminal card showing how to find out whether a machine is running GNU coreutils or the Rust uutils implementation by checking the version string of individual commands, and how the new mv --exchange option swaps two paths atomically.
Which implementation is on your machine, and what the new atomic exchange looks like. PNG

Actual new options, briefly

Three are worth knowing about.

mv --exchange swaps two paths atomically. There is never an instant where either name points at nothing. This is the deployment problem in one command: a live directory and a new build, exchanged with no window in which a request arrives and finds an empty path. Linux has exposed this at the system call level for years through RENAME_EXCHANGE, but reaching it meant writing code rather than typing a command.

rm --one-file-system refuses to cross a mount point, which is the option you want any time a recursive delete runs somewhere a network share or a bind mount might be attached.

install --reflink uses copy on write cloning where the filesystem supports it, so installing a large file costs metadata rather than bytes on btrfs or XFS.

There is also an OpenSSL backend for the checksum utilities, read ahead hints across the same tools, a zero copy fast path in tee, and expr index dropping from quadratic to linear on the length of its inputs.

The gap between this and your machine

Worth being clear about, because changelogs invite the wrong assumption.

Ubuntu 26.04 LTS ships uutils coreutils 0.8.0 as its default userland. This release is 0.10. Nothing described here is on an LTS machine today. Ubuntu 25.10 made the initial switch, and reporting on the transition notes that cp, mv and rm were deliberately left on the GNU implementations while the rest moved across, which is a reasonable way to stage a change this broad.

That also means mv --exchange, the most immediately useful thing in this release, is not something Ubuntu users get by upgrading uutils, because mv is one of the three that did not move.

What we would do

Find out what you are actually running, then leave it alone.

The command to run is sort --version or chmod --version on whichever machine you care about. The output tells you the implementation and the version in one line, and on a mixed system the answer may differ per command. That is worth knowing before you debug something strange, not after.

Beyond that, this is not a release to chase. The value in 0.10 is that a rewrite got more boring, and boring arrives on its own through your distribution. The one group we would nudge is anyone maintaining scripts that will run on Ubuntu 25.10 or later: test them against the uutils implementations now, in a container, rather than discovering the remaining seven percent of behavioural difference during a deployment.

Sources and further reading

Frequently asked questions

How does this compare with what Ubuntu actually ships?

Ubuntu 26.04 LTS ships uutils coreutils 0.8.0 as its default userland, which means the release described here is two versions ahead of what the current LTS carries. That gap matters when you read a changelog: an option like mv --exchange or a fixed edge case in date is not something you have on an LTS machine today, it is something that arrives at a future cycle. Ubuntu 25.10 was the first release to make the switch, and reporting on the transition notes that cp, mv and rm were deliberately kept on GNU implementations while the rest moved, which is a sensible way to stage a change of this size. If you want to know which implementation a given command on your machine is, ask the binary rather than assuming: the version string tells you immediately.

What is the anti panic campaign and why does it matter more than it sounds?

A panic in Rust is an unrecoverable abort. The program stops, prints a message about a thread panicking, and exits with a status that no shell script was written to expect. For a library that is bad. For sort, chmod or install it is worse, because these commands sit inside scripts and pipelines that assume the classic contract: do the work, or fail with a documented exit code and a message on standard error. A panic satisfies neither half of that. The 0.10 release went through more than twenty utilities removing panics and aborts and replacing them with proper error handling, which is unglamorous work that produces no feature you can point at. It is also exactly what has to happen before a rewrite is safe to put under other people's automation.

What does mv --exchange actually do?

It swaps two paths atomically, so that at no observable moment does either name point at nothing or at the wrong thing. The classic problem it solves is the deployment swap: you have a live directory and a freshly built one, and you want the new one in place without a window where a request arrives and finds the path missing. The usual workaround is a symlink and a rename, which works but requires the symlink indirection to exist in the first place. An atomic exchange does it directly on the two real paths. Linux has supported this at the system call level for years through the RENAME_EXCHANGE flag, and it has been reachable from C and from higher level languages, but it was not available as a plain command line option. Now it is.

Is Rust Coreutils actually a drop in replacement yet?

At 93.48 percent of the GNU test suite, close but not identical, and the remaining 29 failures are the interesting part. A pass rate is a blunt instrument: the tests that fail last are usually the strange ones, and strange behaviour is precisely what a script written fifteen years ago might depend on. Our honest read is that for interactive use and for scripts written this decade, the difference is not something you will notice. For a build system, a packaging pipeline or an init script inherited from someone who left, the safe assumption is that you will find at least one thing that behaves differently, and the safe practice is to find it in a test environment rather than in production. The project publishes the pass rate openly, which is more than most rewrites do.

What is in this release for Windows or WebAssembly users?

More than you would expect from a project named after GNU utilities. The 0.10 release adds a wasm32-wasip2 build target, which puts these tools inside WebAssembly runtimes, and continues filling in Windows support with a working timeout implementation, tail -f, sparse file support in cp and CRLF handling fixes in cksum. That cross platform reach is the part of the uutils story that gets least attention and is arguably the strongest argument for it existing at all. GNU coreutils are a Unix answer to a Unix problem. A Rust rewrite compiles to targets that GNU coreutils were never going to reach, which means the same command behaviour becomes available on a Windows build agent or inside a sandboxed runtime without shipping a whole environment to get it.