Ask uutils tail (the Rust rewrite of GNU coreutils) for a file that doesn't exist and it tells you so. Unless the file is called 007:

$ tail 007 # GNU coreutils 9.12 tail: cannot open '007' for reading: No such file or directory $ tail 007 # uutils main tail: cannot open '7' for reading: No such file or directory 

1e3 comes back as 1000, 1.50 as 1.5, +5 as 5. Try tail 1e3 on a directory and you get "error reading '1000'".

Where the 7 comes from

uutils translates its messages with Fluent. Every argument goes through a translate! macro, and that macro checks whether the value parses as a number. If it does, it hands Fluent a number instead of a string, so the locale can format it (digit grouping, decimal separator). That's what you want for "3 files failed". It's not what you want for a file name that just happens to look like a number: Fluent prints the number, not the text you typed.

The project already has translate_text! for exactly this, and date and the sort --check "disorder" line were fixed the same way earlier. The tail fix (#15534, merged a few hours after I opened it) switches the call sites that take a file name, tac (#15541) was merged the same day, and nl (#15544) and the shared checksum code behind md5sum/cksum (#15548) were merged the next morning. The same pattern still shows up in dd, sort, shred and in clap's "unexpected argument" error, all listed in #15533.

The general lesson, if you localise a CLI with Fluent or ICU MessageFormat: anything the user typed (paths, operands, input lines) should go in as a string. Let only real counts be numbers.

Catching it automatically

I found this with behave, which probes a command as a black box, records what the original does and replays it against a rewrite. Its generated cases always included "missing file", but with the name does-not-exist.txt, which no number parser will touch. Since v0.1.6 behave probe also adds a missing-file case with the names 007 and 1e3:

✗ missing file named like a number 0008-missing-file-named-like-a-number.yaml $ tail 007 1e3 stderr: - $CMD: cannot open '007' for reading: No such file or directory - $CMD: cannot open '1e3' for reading: No such file or directory + $CMD: cannot open '7' for reading: No such file or directory + $CMD: cannot open '1000' for reading: No such file or directory 

It costs one case per tool and checks something every port that translates its messages can get wrong.

go install github.com/emirmrkaljevic/behave/cmd/behave`latest # or: brew install emirmrkaljevic/tap/behave behave probe tail --out spec-tail behave diff spec-tail --impl ./target/release/tail 

behave is open source (MIT): https://github.com/emirmrkaljevic/behave · more from me on GitHub