<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>uutils</title>
    <subtitle>uutils — cross-platform Rust reimplementations of essential Unix command-line utilities</subtitle>
    <link rel="self" type="application/atom+xml" href="https://uutils.org/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://uutils.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-31T00:00:00+00:00</updated>
    <id>https://uutils.org/atom.xml</id>
    <entry xml:lang="en">
        <title>Pointing at the error: compiler-style diagnostics in uutils coreutils</title>
        <published>2026-08-31T00:00:00+00:00</published>
        <updated>2026-08-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            Sylvestre Ledru
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://uutils.org/blog/2026-08-error-diagnostics/"/>
        <id>https://uutils.org/blog/2026-08-error-diagnostics/</id>
        
        <content type="html" xml:base="https://uutils.org/blog/2026-08-error-diagnostics/">&lt;p&gt;For 50 years, Coreutils have never stopped evolving. Now, we&#39;re pushing that innovation further by rethinking how they report errors.&lt;/p&gt;
&lt;p&gt;Unix tools report errors as a single line on stderr. That line says what went wrong, not where. For most commands there is nowhere else to point anyway, but a few take arguments that are small languages: a &lt;code&gt;test&lt;/code&gt; expression, a &lt;code&gt;chmod&lt;/code&gt; mode, a &lt;code&gt;sort&lt;/code&gt; key, a &lt;code&gt;tr&lt;/code&gt; set. When one of those fails to parse, what you actually want to know is which argument, or which character of it, the parser tripped over.&lt;/p&gt;
&lt;p&gt;rustc has been answering that question with a caret for years, and &lt;a rel=&quot;external&quot; href=&quot;https://codeberg.org/zesterer/ariadne&quot;&gt;ariadne&lt;/a&gt; puts the same rendering one dependency away. The idea of bringing it to a command-line tool comes from &lt;a href=&quot;/awk&quot;&gt;uutils awk&lt;/a&gt;, which already reports errors in an awk program that way; coreutils arguments are smaller languages, but they parse just the same. Starting with 0.11.0, coreutils uses it. 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 when we have something useful to say about it.&lt;/p&gt;
&lt;h3 id=&quot;what-it-looks-like&quot;&gt;What it looks like&lt;/h3&gt;
&lt;p&gt;Start with &lt;code&gt;tr&lt;/code&gt;, whose GNU message assumes you already know what a collating sequence is.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;tr&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; tr &amp;#x27;qw[y-b]&amp;#x27; x&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;tr: range-endpoints of &amp;#x27;y-b&amp;#x27; are in reverse collating sequence order&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;tr&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/tr.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; tr &amp;#x27;qw[y-b]&amp;#x27; x&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;tr: range-endpoints of &amp;#x27;y-b&amp;#x27; are in reverse collating sequence order
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; tr:1:7 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;tr qw[&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;y-b&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt;] x&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;       &lt;span class=&quot;a-e&quot;&gt;─┬─&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;        &lt;span class=&quot;a-e&quot;&gt;╰───&lt;/span&gt; did you mean &amp;#x27;b-y&amp;#x27;?
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a range goes from the lower character to the higher one, as in a-z
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=tr+%27qw%5By-b%5D%27+x&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;cut&lt;/code&gt; list can be long, with a single bad item in it.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;cut&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; cut -f 1,4-2,9-12 notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;cut: invalid decreasing range
Try &amp;#x27;cut --help&amp;#x27; for more information.&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;cut&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/cut.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; cut -f 1,4-2,9-12 notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;cut: invalid decreasing range
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; cut:1:10 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;cut -f 1,&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;4-2&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt;,9-12 notes.txt&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;          &lt;span class=&quot;a-e&quot;&gt;─┬─&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;           &lt;span class=&quot;a-e&quot;&gt;╰───&lt;/span&gt; this range ends before it starts
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a list is N, N-M, N- or -M, separated by commas, as in -f1,4-6,9-
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;
Try &amp;#x27;cut --help&amp;#x27; for more information.&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=cut+-f+1%2C4-2+fruits.txt&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The caret does not have to cover a whole argument. It can land on one character.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;chmod&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; chmod &amp;#x27;g+rw?x&amp;#x27; notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;chmod: invalid operator (expected +, -, or =, but found ?)&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;chmod&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/chmod.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; chmod &amp;#x27;g+rw?x&amp;#x27; notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;chmod: invalid operator (expected +, -, or =, but found ?)
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; chmod:1:5 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;g+rw&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt;x notes.txt&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;     &lt;span class=&quot;a-e&quot;&gt;─&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a mode is either octal, as in 644, or clauses such as u+rwx,go-w
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;sort&lt;/code&gt; keys are short enough that a stray character is easy to miss.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;sort&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; sort -k2.3x notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;sort: stray character in field spec: invalid field specification &amp;#x27;2.3x&amp;#x27;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;sort&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/sort.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; sort -k2.3x notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;sort: stray character in field spec: invalid field specification &amp;#x27;2.3x&amp;#x27;
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; sort:1:11 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;sort -k2.3&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt; notes.txt&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;           &lt;span class=&quot;a-e&quot;&gt;─&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a key is FIELD[.CHAR][OPTS][,FIELD[.CHAR][OPTS]], as in -k2.3,4nr
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=sort+-k2.3x+fruits.txt&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;env -S&lt;/code&gt; takes a whole command line and splits it the way a shell would. The old message could only quote the offending fragment back at you. Note that the string contains spaces, so it is echoed back quoted, and the caret still lands inside the quotes.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;env&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; env -S &amp;#x27;echo ${1FOO}&amp;#x27;&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;env: only ${VARNAME} expansion is supported, error at: ${1FOO}&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;env&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/env.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; env -S &amp;#x27;echo ${1FOO}&amp;#x27;&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;env: only ${VARNAME} expansion is supported, error at: ${1FOO}
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; env:1:14 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;env -S &amp;#x27;echo &lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;${1&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt;FOO}&amp;#x27;&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;              &lt;span class=&quot;a-e&quot;&gt;─┬─&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;               &lt;span class=&quot;a-e&quot;&gt;╰───&lt;/span&gt; a variable name cannot start with a digit
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: only $NAME and ${NAME} are expanded; the other shell forms are not
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;test&lt;/code&gt; builds its expression out of separate arguments. The report echoes the expression on its own, without the &lt;code&gt;test&lt;/code&gt; in front, and marks the argument that broke it.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;test&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; test 7 -eq zap&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;test: invalid integer &amp;#x27;zap&amp;#x27;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;test&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/test.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; test 7 -eq zap&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;test: invalid integer &amp;#x27;zap&amp;#x27;
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; test:1:7 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;7 -eq &lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;zap&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;       &lt;span class=&quot;a-e&quot;&gt;───&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: -eq, -ne, -lt, -le, -gt and -ge compare integers; use =, !=, &amp;lt; or &amp;gt; to compare strings
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;       -eq equal, -ne not equal, -lt less than, -le less than or equal, -gt greater than, -ge greater than or equal
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=test+7+-eq+zap&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A SIZE is a number followed by a unit. The report says which half was rejected.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;head&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; head -c 1fb notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;head: invalid number of bytes: &amp;#x27;1fb&amp;#x27;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;head&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/head.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; head -c 1fb notes.txt&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;head: invalid number of bytes: &amp;#x27;1fb&amp;#x27;
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; head:1:10 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;head -c 1&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;fb&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt; notes.txt&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;          &lt;span class=&quot;a-e&quot;&gt;─┬&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;           &lt;span class=&quot;a-e&quot;&gt;╰──&lt;/span&gt; not a known unit
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a size is a number and an optional unit: K, M, G and so on for 1024, KB, MB, GB for 1000
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=head+-c+1fb+fruits.txt&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One parser handles every SIZE in the suite, so the same report shows up for &lt;code&gt;tail -c&lt;/code&gt;, &lt;code&gt;truncate -s&lt;/code&gt;, &lt;code&gt;split -b&lt;/code&gt;, &lt;code&gt;shred -s&lt;/code&gt;, &lt;code&gt;od -N&lt;/code&gt;, &lt;code&gt;sort -S&lt;/code&gt;, the block sizes of &lt;code&gt;du -B&lt;/code&gt;, &lt;code&gt;df -B&lt;/code&gt; and &lt;code&gt;ls --block-size&lt;/code&gt;, and the threshold of &lt;code&gt;du -t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;numfmt --format&lt;/code&gt; is a printf-style format that allows exactly one conversion. The old message just restated the rule. The annotation names the conversion you actually wrote.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;numfmt&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; numfmt --format=%q 1000&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;numfmt: invalid format &amp;#x27;%q&amp;#x27;, directive must be %[0][&amp;#x27;][-][N][.][N]f&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;numfmt&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;diag-replay&quot; data-cast=&quot;/casts/numfmt.json&quot;&gt;
      &lt;div class=&quot;diag-fallback&quot;&gt;
        &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; numfmt --format=%q 1000&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;numfmt: invalid format &amp;#x27;%q&amp;#x27;, directive must be %[0][&amp;#x27;][-][N][.][N]f
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; numfmt:1:18 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;numfmt --format=%&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt; 1000&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;                  &lt;span class=&quot;a-e&quot;&gt;┬&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;                  &lt;span class=&quot;a-e&quot;&gt;╰──&lt;/span&gt; f is the only conversion numfmt has; %d, %e, %g and the other C conversions are not accepted
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a format is [PREFIX]%[0][&amp;#x27;][-][WIDTH][.PRECISION]f[SUFFIX], as in &amp;quot;%&amp;#x27;-10.2f&amp;quot;
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=numfmt+--format%3D%25q+1000&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;csplit&lt;/code&gt; patterns contain regexes, and the regex engine already knows which character it choked on. We were simply throwing that position away.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;csplit&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; csplit notes.txt &amp;#x27;/a{2,1}/&amp;#x27;&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;csplit: &amp;#x27;/a{2,1}/&amp;#x27;: invalid pattern&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;term term-diag&quot;&gt;
  &lt;div class=&quot;term-bar&quot;&gt;
    &lt;span class=&quot;t&quot;&gt;csplit&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;term-body&quot;&gt;
    &lt;div class=&quot;term-prompt&quot;&gt;&lt;span class=&quot;pr&quot;&gt;$&lt;/span&gt; csplit notes.txt &amp;#x27;/a{2,1}/&amp;#x27;&lt;/div&gt;
&lt;pre class=&quot;diag&quot;&gt;csplit: &amp;#x27;/a{2,1}/&amp;#x27;: invalid pattern
   &lt;span class=&quot;a-d&quot;&gt;╭─[&lt;/span&gt; csplit:1:20 &lt;span class=&quot;a-d&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;a-d&quot;&gt;│&lt;/span&gt;
 &lt;span class=&quot;a-d&quot;&gt;1 │&lt;/span&gt; &lt;span class=&quot;a-s&quot;&gt;csplit notes.txt /a&lt;/span&gt;&lt;span class=&quot;a-e&quot;&gt;{2,1}&lt;/span&gt;&lt;span class=&quot;a-s&quot;&gt;/&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;                    &lt;span class=&quot;a-e&quot;&gt;──┬──&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;                      &lt;span class=&quot;a-e&quot;&gt;╰────&lt;/span&gt; invalid repetition count range, the start must be &amp;lt;= the end
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt;
 &lt;span class=&quot;a-f&quot;&gt;  │&lt;/span&gt; &lt;span class=&quot;a-h&quot;&gt;Help&lt;/span&gt;: a pattern is a line number N, /REGEXP/[OFFSET] or %REGEXP%[OFFSET], each optionally followed by {N} or {*}
&lt;span class=&quot;a-d&quot;&gt;───╯&lt;/span&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=csplit+fruits.txt+%27%2Fa%7B2%2C1%7D%2F%27&quot;&gt;Try it in the playground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That label comes straight from the regex engine and is not translated, since it is the only place the wording exists.&lt;/p&gt;
&lt;h3 id=&quot;where-it-applies&quot;&gt;Where it applies&lt;/h3&gt;
&lt;p&gt;28 utilities use it in 0.11.0. The linked examples run in the playground; the others are for utilities the WebAssembly build does not ship, so try those locally:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Utility&lt;/th&gt;&lt;th&gt;What the caret points at&lt;/th&gt;&lt;th&gt;Try it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;test&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the argument that made the expression fail&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=test+7+-eq+zap&quot;&gt;&lt;code&gt;test 7 -eq zap&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;expr&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the argument that made the expression fail&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=expr+9+%2B+foo&quot;&gt;&lt;code&gt;expr 9 + foo&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;chmod&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing clause (or character) of an invalid symbolic or octal mode&lt;/td&gt;&lt;td&gt;&lt;code&gt;chmod &#39;g+rw?x&#39; fruits.txt&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;mkdir&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the mode given to &lt;code&gt;-m&lt;/code&gt;/&lt;code&gt;--mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=mkdir+-m+u%2Bq+mydir&quot;&gt;&lt;code&gt;mkdir -m u+q mydir&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;mkfifo&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the mode given to &lt;code&gt;-m&lt;/code&gt;/&lt;code&gt;--mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;mkfifo -m u+q mypipe&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;mknod&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the mode given to &lt;code&gt;-m&lt;/code&gt;/&lt;code&gt;--mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;mknod -m u+q mydev c 1 3&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;install&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the mode given to &lt;code&gt;-m&lt;/code&gt;/&lt;code&gt;--mode&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;install -m u+q fruits.txt dest&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;tr&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the part of a set that is at fault (bad class, backwards range, bad repeat count, …)&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=tr+%27qw%5By-b%5D%27+x&quot;&gt;&lt;code&gt;tr &#39;qw[y-b]&#39; x&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sort&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of a &lt;code&gt;-k&lt;/code&gt;/&lt;code&gt;--key&lt;/code&gt; or field specification, or of the SIZE given to &lt;code&gt;-S&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=sort+-k2.3x+fruits.txt&quot;&gt;&lt;code&gt;sort -k2.3x fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;numfmt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of a &lt;code&gt;--format&lt;/code&gt; or &lt;code&gt;--field&lt;/code&gt; specification, the value given to &lt;code&gt;--from&lt;/code&gt;, &lt;code&gt;--to&lt;/code&gt;, &lt;code&gt;--from-unit&lt;/code&gt;, &lt;code&gt;--to-unit&lt;/code&gt;, &lt;code&gt;--padding&lt;/code&gt; or &lt;code&gt;--header&lt;/code&gt;, or the input number itself&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=numfmt+--format%3D%25q+1000&quot;&gt;&lt;code&gt;numfmt --format=%q 1000&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;printf&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing conversion or escape in the format string&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=printf+%255.2c+q&quot;&gt;&lt;code&gt;printf %5.2c q&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;seq&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing conversion in the format given to &lt;code&gt;-f&lt;/code&gt;/&lt;code&gt;--format&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=seq+-f+%255.2c+1+3&quot;&gt;&lt;code&gt;seq -f %5.2c 1 3&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;stat&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing directive of a &lt;code&gt;-c&lt;/code&gt;/&lt;code&gt;--format&lt;/code&gt; or &lt;code&gt;--printf&lt;/code&gt; format&lt;/td&gt;&lt;td&gt;&lt;code&gt;stat -c %d%.3 fruits.txt&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;env&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of a &lt;code&gt;-S&lt;/code&gt;/&lt;code&gt;--split-string&lt;/code&gt; string&lt;/td&gt;&lt;td&gt;&lt;code&gt;env -S &#39;echo ${1FOO}&#39;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;dd&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing key, value or flag of a &lt;code&gt;KEY=VALUE&lt;/code&gt; operand&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=dd+conv%3Ducase%2Czap&quot;&gt;&lt;code&gt;dd conv=ucase,zap&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;join&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing field of the output format given to &lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=join+-o+1.2%2C2.x+fruits.txt+fruits.txt&quot;&gt;&lt;code&gt;join -o 1.2,2.x fruits.txt fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;cut&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing range in the list given to &lt;code&gt;-b&lt;/code&gt;, &lt;code&gt;-c&lt;/code&gt;, &lt;code&gt;-f&lt;/code&gt; or &lt;code&gt;-F&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=cut+-f+1%2C4-2+fruits.txt&quot;&gt;&lt;code&gt;cut -f 1,4-2 fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;csplit&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing pattern operand, the character of its regex that broke, or the format given to &lt;code&gt;-b&lt;/code&gt;/&lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=csplit+fruits.txt+%27%2Fa%28b%2F%27&quot;&gt;&lt;code&gt;csplit fruits.txt &#39;/a(b/&#39;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;split&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-b&lt;/code&gt;, &lt;code&gt;-C&lt;/code&gt; or &lt;code&gt;-l&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=split+-b+7zq+fruits.txt&quot;&gt;&lt;code&gt;split -b 7zq fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;shred&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-s&lt;/code&gt;/&lt;code&gt;--size&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=shred+-s+4vv+fruits.txt&quot;&gt;&lt;code&gt;shred -s 4vv fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;head&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-c&lt;/code&gt; or &lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=head+-c+1fb+fruits.txt&quot;&gt;&lt;code&gt;head -c 1fb fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;tail&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-c&lt;/code&gt; or &lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=tail+-c+1fb+fruits.txt&quot;&gt;&lt;code&gt;tail -c 1fb fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;truncate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-s&lt;/code&gt;/&lt;code&gt;--size&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=truncate+-s+10fb+fruits.txt&quot;&gt;&lt;code&gt;truncate -s 10fb fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;od&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-j&lt;/code&gt;, &lt;code&gt;-N&lt;/code&gt;, &lt;code&gt;-S&lt;/code&gt; or &lt;code&gt;-w&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=od+-N+3zz+fruits.txt&quot;&gt;&lt;code&gt;od -N 3zz fruits.txt&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;du&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-B&lt;/code&gt;/&lt;code&gt;--block-size&lt;/code&gt; or &lt;code&gt;-t&lt;/code&gt;/&lt;code&gt;--threshold&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;du -B 1fb&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;df&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;-B&lt;/code&gt;/&lt;code&gt;--block-size&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;df -B 1fb&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the SIZE given to &lt;code&gt;--block-size&lt;/code&gt; (also &lt;code&gt;dir&lt;/code&gt; and &lt;code&gt;vdir&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://uutils.org/playground/?cmd=ls+--block-size%3D1fb&quot;&gt;&lt;code&gt;ls --block-size=1fb&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;stdbuf&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the failing part of the buffering mode given to &lt;code&gt;-i&lt;/code&gt;, &lt;code&gt;-o&lt;/code&gt; or &lt;code&gt;-e&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;stdbuf -o 6pq head&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;compatibility-first&quot;&gt;Compatibility first&lt;/h3&gt;
&lt;p&gt;Being a drop-in replacement for GNU coreutils comes first, so this is strictly an interactive nicety:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reports are only rendered when &lt;strong&gt;stderr is a terminal&lt;/strong&gt;. In a script, a pipe or a test suite, each utility keeps printing exactly the plain one-line message shown as &quot;Before&quot; in the examples above, so anything that greps stderr keeps working.&lt;/li&gt;
&lt;li&gt;Exit codes are unchanged.&lt;/li&gt;
&lt;li&gt;Colors are only used on a terminal and respect &lt;a rel=&quot;external&quot; href=&quot;https://no-color.org/&quot;&gt;&lt;code&gt;NO_COLOR&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Like the rest of uutils, the messages, labels and help lines are localized; translations are managed on &lt;a rel=&quot;external&quot; href=&quot;https://hosted.weblate.org/projects/rust-coreutils/&quot;&gt;Weblate&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It can be compiled out to save a little space: the rendering sits behind the &lt;code&gt;feat_diagnostics&lt;/code&gt; cargo feature (on by default), and building without it drops the &lt;code&gt;ariadne&lt;/code&gt; dependency while every utility keeps its plain messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;turning-it-on-and-off&quot;&gt;Turning it on and off&lt;/h3&gt;
&lt;p&gt;By default the rendering keys off stderr being a terminal and nothing else, which is usually but not always what you want. &lt;code&gt;UUTILS_DIAG&lt;/code&gt; overrides it: &lt;code&gt;always&lt;/code&gt; draws the report even into a file or a pipe, &lt;code&gt;never&lt;/code&gt; keeps the plain line even at a terminal, and &lt;code&gt;auto&lt;/code&gt;, or an unset variable, decides from stderr as before. An unrecognized value is deliberately not an error. This is the kind of variable people export from a shell profile once and forget about, and a typo in it should not be able to make a utility fail.&lt;/p&gt;
&lt;p&gt;There is no command-line flag to go with it. The utilities that would need one most cannot have it: in &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;printf&lt;/code&gt; and &lt;code&gt;expr&lt;/code&gt;, a new option would be either illegal or ambiguous with the operands themselves.&lt;/p&gt;
&lt;p&gt;To get a report out of a script or a CI log, to paste into a bug report for instance:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ UUTILS_DIAG=always sort -k2.3x notes.txt 2&amp;gt; parse.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ cat parse.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sort: stray character in field spec: invalid field specification &amp;#39;2.3x&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ╭─[ sort:1:11 ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1 │ sort -k2.3x notes.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │           ─&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │ Help: a key is FIELD[.CHAR][OPTS][,FIELD[.CHAR][OPTS]], as in -k2.3,4nr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;───╯&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Colors are decided separately, and still by the terminal: a report forced into a file is written without them, so there are no escape sequences to strip back out. &lt;a rel=&quot;external&quot; href=&quot;https://no-color.org/&quot;&gt;&lt;code&gt;NO_COLOR&lt;/code&gt;&lt;/a&gt; sits in between at a terminal, where the report is still drawn, just in plain text.&lt;/p&gt;
&lt;p&gt;The two tricks people used before the variable existed still work. Sending stderr somewhere that is not a terminal gets the plain line:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ sort -k2.3x notes.txt 2&amp;gt;&amp;amp;1 | cat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sort: stray character in field spec: invalid field specification &amp;#39;2.3x&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And giving a command a pty (&lt;code&gt;script -qec &quot;sort -k2.3x notes.txt&quot; /dev/null&lt;/code&gt;, or &lt;code&gt;unbuffer&lt;/code&gt; from expect) gets the report back, which is handy when the command has to run under a terminal for other reasons.&lt;/p&gt;
&lt;h3 id=&quot;what-comes-next&quot;&gt;What comes next&lt;/h3&gt;
&lt;p&gt;coreutils is where this starts, not where it stops. The rendering lives in &lt;code&gt;uucore::diagnostics&lt;/code&gt;, which the other uutils projects already depend on, so picking it up is mostly a matter of handing the parser&#39;s error a span. &lt;a href=&quot;/findutils&quot;&gt;findutils&lt;/a&gt; and &lt;a href=&quot;/sed&quot;&gt;sed&lt;/a&gt; are being wired up now; a &lt;code&gt;find&lt;/code&gt; expression and a &lt;code&gt;sed&lt;/code&gt; script are exactly the kind of small languages a caret helps with, and &lt;a href=&quot;/grep&quot;&gt;grep&lt;/a&gt;, &lt;a href=&quot;/awk&quot;&gt;awk&lt;/a&gt; and the rest have the same regexes and format strings to point at.&lt;/p&gt;
&lt;p&gt;If a utility you use still prints an unhelpful one-liner, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/coreutils/blob/main/CONTRIBUTING.md&quot;&gt;patches are welcome&lt;/a&gt;!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Try Uutils Coreutils directly in your browser</title>
        <published>2025-04-04T00:00:00+00:00</published>
        <updated>2025-04-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            Sylvestre Ledru
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://uutils.org/blog/2025-04-playground/"/>
        <id>https://uutils.org/blog/2025-04-playground/</id>
        
        <content type="html" xml:base="https://uutils.org/blog/2025-04-playground/">&lt;p&gt;We are happy to announce the &lt;a href=&quot;/playground&quot;&gt;Uutils playground&lt;/a&gt; - an interactive terminal that lets you run real Rust Uutils Coreutils directly in your browser, with no installation, no server, and no network round-trips after the initial page load.&lt;/p&gt;
&lt;p&gt;Just open the page and start typing commands like &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;factor&lt;/code&gt;, or any of the 60+ utilities available. You can pipe commands together (&lt;code&gt;sort fruits.txt | uniq -c | sort -rn&lt;/code&gt;), use redirections (&lt;code&gt;echo hello &amp;gt; file.txt&lt;/code&gt;, &lt;code&gt;cat &amp;lt; file.txt&lt;/code&gt;), explore the virtual filesystem, and even switch between 30+ languages using the locale dropdown.&lt;/p&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How it works&lt;/h3&gt;
&lt;p&gt;The Uutils Coreutils are compiled to WebAssembly (targeting &lt;code&gt;wasm32-wasip1&lt;/code&gt;) as a single multicall binary - similar to BusyBox. When you type a command, a minimal JavaScript shell parses your input, sets up pipes between stages, and executes each one by instantiating the WASM binary with the right arguments. A virtual in-memory filesystem backed by &lt;a rel=&quot;external&quot; href=&quot;https://github.com/bjorn3/browser_wasi_shim&quot;&gt;browser_wasi_shim&lt;/a&gt; provides file I/O. Everything runs client-side - once loaded, the playground works entirely offline.&lt;/p&gt;
&lt;p&gt;An important distinction worth noting: &lt;strong&gt;coreutils only provides individual commands&lt;/strong&gt; (&lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, etc.). Features like &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;then&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; loops, variable expansion (&lt;code&gt;$VAR&lt;/code&gt;), and globbing (&lt;code&gt;*.txt&lt;/code&gt;) are shell features provided by Bash, Zsh, or similar - not by coreutils. The playground&#39;s JavaScript shell is intentionally minimal, keeping the focus on the coreutils themselves.&lt;/p&gt;
&lt;p&gt;For a deeper look at the architecture - including diagrams, the multicall dispatch mechanism, the &lt;code&gt;feat_wasm&lt;/code&gt; feature gate, and how localization is handled - check out the &lt;a href=&quot;/playground-how-it-works&quot;&gt;full technical deep-dive&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;try-it-break-it-improve-it&quot;&gt;Try it, break it, improve it&lt;/h3&gt;
&lt;p&gt;Give the &lt;a href=&quot;/playground&quot;&gt;playground&lt;/a&gt; a spin and let us know what you think! Contributions are welcome - whether it is improving WASI compatibility to enable more commands, adding translations via &lt;a rel=&quot;external&quot; href=&quot;https://hosted.weblate.org/projects/rust-coreutils/&quot;&gt;Weblate&lt;/a&gt;, or enhancing the playground shell itself.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Extending the Coreutils project - Rewriting base tools in Rust</title>
        <published>2025-02-01T00:00:00+00:00</published>
        <updated>2025-02-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            Sylvestre Ledru
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://uutils.org/blog/2025-02-extending/"/>
        <id>https://uutils.org/blog/2025-02-extending/</id>
        
        <content type="html" xml:base="https://uutils.org/blog/2025-02-extending/">&lt;p&gt;As I &lt;a rel=&quot;external&quot; href=&quot;https://sylvestre.ledru.info/coreutils-fosdem-2025/&quot;&gt;just presented at FOSDEM&lt;/a&gt;,  we are moving into the next phase of the uutils project.&lt;/p&gt;
&lt;p&gt;Over the last five years, we have been working on reimplementing some of the key Linux tools in Rust. We started with the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/coreutils&quot;&gt;Coreutils&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/findutils&quot;&gt;findutils&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As we approach feature parity with the GNU Coreutils implementation, and as its adoption in production environments continues to expand, we have been thinking about what is next.&lt;/p&gt;
&lt;p&gt;Given the very positive feedback around this initiative, we are going to extend our efforts to rewrite other parts of the modern Linux/Unix/Mac stack in Rust (still with Windows support in mind when relevant). These efforts will be managed under the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/&quot;&gt;uutils umbrella&lt;/a&gt;, which will allow us to maintain a cohesive and unified approach across various utilities.&lt;/p&gt;
&lt;p&gt;We also noticed a lot of contributions on these projects coming from a diverse group of hackers (530 different contributors on Coreutils alone!). With the growing enthusiasm for Rust and the eagerness to learn it, now is the best time to push this project forward. Rewriting in Rust will help with the long-term maintenance of the ecosystem, ensuring it stays robust, safe, and welcoming for new generations of contributors.&lt;/p&gt;
&lt;h3 id=&quot;vision-for-the-future&quot;&gt;Vision for the Future&lt;/h3&gt;
&lt;p&gt;As we expand the scope of the project, we are working on a future where Rust becomes the backbone of essential Linux, Unix, and potentially macOS system tools. Our focus will be on improving security, ensuring long-term maintainability, and optimizing performance for both modern and legacy systems. Through the uutils umbrella, we aim to create a more secure, efficient, and scalable alternative to the traditional tools, replacing software developed in older, less secure programming languages like C.&lt;/p&gt;
&lt;p&gt;This project is also an investment for the future. C is becoming less popular with the next generation of developers. Just like how the Linux kernel continues to evolve and includes Rust, it is our responsibility to upgrade the core utilities of the system to a modern, safer programming language. By doing so, we ensure that the essential tools used in Linux/Unix systems remain relevant, maintainable, and accessible to future contributors.&lt;/p&gt;
&lt;h3 id=&quot;specific-benefits-of-rust&quot;&gt;Specific Benefits of Rust&lt;/h3&gt;
&lt;p&gt;Rust offers several advantages over C/C++, particularly in terms of memory safety, concurrency, and performance. By eliminating common security issues such as null pointer dereferences and buffer overflows, Rust allows us to build tools that are inherently safer. Its modern compiler tooling also enables us to optimize performance without sacrificing code safety, ensuring that our utilities can handle the demands of modern computing environments while remaining easy to maintain.&lt;/p&gt;
&lt;h3 id=&quot;challenges-and-opportunities&quot;&gt;Challenges and Opportunities&lt;/h3&gt;
&lt;p&gt;As with any large-scale reimplementation, there are challenges to overcome. Porting complex utilities from C to Rust requires careful consideration of edge cases and platform-specific behaviors. Additionally, ensuring full compatibility across Linux, Unix, and macOS environments presents unique challenges. However, these challenges also offer opportunities for growth and innovation, allowing us to extend and refine core system utilities for modern needs. Rust&#39;s modern design gives us the chance to improve both security and performance while maintaining cross-platform compatibility.&lt;/p&gt;
&lt;h3 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h3&gt;
&lt;p&gt;For the next phase of the project, we are adopting the same approach: a drop-in replacement of the C implementations. Here&#39;s what&#39;s coming next:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/acl&quot;&gt;acl&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Access control list utilities&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/bsdutils&quot;&gt;bsdutils&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Basic utilities for BSD compatibility&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/coreutils&quot;&gt;coreutils&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Basic utilities for the system&lt;/td&gt;&lt;td&gt;Production level&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/diffutils&quot;&gt;diffutils&lt;/a&gt;&lt;/td&gt;&lt;td&gt;File comparison utilities&lt;/td&gt;&lt;td&gt;Almost ready&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/findutils&quot;&gt;findutils&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Utilities for finding files&lt;/td&gt;&lt;td&gt;Getting close to completion&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/hostname&quot;&gt;hostname&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Utility to show or set system hostname&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/login&quot;&gt;login&lt;/a&gt;&lt;/td&gt;&lt;td&gt;User login management utilities&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/procps&quot;&gt;procps&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Utilities for monitoring and controlling processes&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils/util-linux&quot;&gt;util-linux&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Utilities essential for Linux systems&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;These packages are part of the essential list for Debian and Ubuntu, and we&#39;re excited to push their Rust reimplementation further.&lt;/p&gt;
&lt;h3 id=&quot;gsoc-2024-participation&quot;&gt;GSoC 2024 Participation&lt;/h3&gt;
&lt;p&gt;In 2024, we had the pleasure of mentoring three students during Google Summer of Code (GSoC):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sreehari Prasad&lt;/strong&gt; worked on improving the support of Rust CCoreutils. His focus was on making uutils compatible with the GNU coreutils test suite. Sreehari resolved most of the failing tests for the &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;, and &lt;code&gt;ls&lt;/code&gt; utilities and significantly enhanced compatibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hanbings&lt;/strong&gt; tackled the implementation of key GNU &lt;code&gt;findutils&lt;/code&gt; utilities like &lt;code&gt;xargs&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; in Rust. His work focused on improving compatibility with the GNU suite while enhancing performance, resulting in major progress on missing features and test code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Krysztal Huang&lt;/strong&gt; worked on implementing the &lt;code&gt;procps&lt;/code&gt; suite, which includes utilities like &lt;code&gt;slabtop&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;pgrep&lt;/code&gt;, &lt;code&gt;pidof&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;pidwait&lt;/code&gt;, and &lt;code&gt;snice&lt;/code&gt;. This project involved implementing some of these commands.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;call-to-action-for-contributors&quot;&gt;Call to Action for Contributors&lt;/h3&gt;
&lt;p&gt;Contributors who are passionate about system-level programming and Rust are always welcome. Whether you&#39;re experienced with GNU utilities or just learning Rust, your contributions will be invaluable to this
project. You can get involved by picking up good-first issues, reviewing code, or even helping us test new features across various platforms. The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/uutils&quot;&gt;uutils GitHub organization&lt;/a&gt; has all the information you need to get started.
You can also sponsor the project through &lt;a rel=&quot;external&quot; href=&quot;https://github.com/sponsors/uutils&quot;&gt;GitHub Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;faq&quot;&gt;FAQ&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;How long is it going to take?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some programs, like &lt;code&gt;diff&lt;/code&gt;, &lt;code&gt;acl&lt;/code&gt;, or &lt;code&gt;hostname&lt;/code&gt;, could be completed quickly, while others will take years to finish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you hate the GNU project?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not at all. We often contribute to the upstream implementations when we identify issues, add missing tests, and so on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why the MIT License?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For consistency purposes. We&#39;re not interested in a license debate and will continue to use the MIT license, as we did with Coreutils.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The binaries are too big. Does it really matter?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, Rust binaries are generally bigger than GNU&#39;s, but we don&#39;t think it&#39;s a blocker, even for embedded devices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is it really safer?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While Rust is better than C/C++ for security, these programs are often already very safe. Security is not the key argument for us in this rewrite even if Rust provides some automatic improvements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What about performance?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although we haven&#39;t started optimizing yet, Rust&#39;s design facilitates performance improvements naturally. We are confident that, in time, these tools will match or exceed the performance of their GNU counterparts.&lt;/p&gt;
</content>
        
    </entry>
</feed>
