Skip to content

stat: always end --format output with a newline, and read a directive's first byte - #15354

Closed
ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:stat-format-newline
Closed

ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:stat-format-newline

Conversation

@ozenyunus35

@ozenyunus35 ozenyunus35 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Closes #15347

With a user --format, GNU prints a newline after the output even when the format already ends with one, so stat -c $'%i\n' / prints the inode and an empty line. We skipped it when the format ended with \n.

The newline is added only for a user --format; the built-in formats (plain stat, -t, -f) already end with one and still print exactly one.

Tests: test_format_always_ends_with_a_newline (fails without the change) and test_default_formats_end_with_one_newline. The normal_format unit test is updated.

I used an AI assistant to help draft parts of the code and tests; I reviewed the changes and ran the tests myself.

…'s first byte

GNU appends the newline after --format output unconditionally (its
trailing delimiter), so `stat -c $'%i\\n'` prints an empty line after the
inode; we skipped it when the format already ended with a newline.

GNU also reads the format byte by byte: `%` before a multibyte character
is an unknown directive on its first byte (`?`), and the character's other
bytes are printed as they are. We dropped them.

Closes uutils#15347
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/stat/stat-fmt. tests/stat/stat-fmt is passing on 'main'. Maybe you have to rebase?

Comment thread src/uu/stat/src/stat.rs Outdated
match chars.get(i) {
Some('%') => match Self::handle_percent_case(&chars, &mut i, bound, format_str) {
Ok(token) => tokens.push(token),
Ok(token) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a separate fix from the newline one, could you please split it into its own pr?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it from this PR.

Comment thread src/uu/stat/src/stat.rs Outdated
if !use_printf && !format_str.ends_with('\n') {
// GNU ends every --format output with a newline, even when the format
// already ends with one.
if !use_printf {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default formats already end with \n and go through here too, so won't plain stat . and stat -t . now print an extra empty line?
maybe only add it for a user-given format

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch, plain stat printed an extra empty line. The newline is now only added for a user --format, the built-in formats are left alone.

}

#[test]
fn test_format_always_ends_with_a_newline() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also add a test that stat -t . ends with exactly one newline, the current tests trim it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test_default_formats_end_with_one_newline, it checks stat, stat -t, stat -f and stat -f -t end with exactly one newline.

…byte

The default formats already end with a newline, so adding one for every
non-printf format printed an empty line after plain stat and stat -t.
Only a user --format gets GNU's trailing newline now.

The multibyte directive change moves to its own PR.
@ozenyunus35

Copy link
Copy Markdown
Contributor Author

Closing this, as I can't follow up on it further. Thanks for the reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(stat): a \n or valid utf8 encoded char in --format in it own is ignored, while gnu applies it

2 participants