Skip to content

extract: add -O/--to-stdout - #403

Closed
ozenyunus35 wants to merge 4 commits into
uutils:mainfrom
ozenyunus35:to-stdout
Closed

ozenyunus35 wants to merge 4 commits into
uutils:mainfrom
ozenyunus35:to-stdout

Conversation

@ozenyunus35

Copy link
Copy Markdown
Contributor

Closes #196

With -O/--to-stdout, extract writes the contents of regular members to standard output instead of creating them, like GNU tar. Other member types (directories, links, ...) are skipped. With -v, the member names go to standard error so they don't mix with the contents.

extract_archive gets a to_stdout flag; the unit test and bench callers pass false. Added test_extract_to_stdout, which checks that nothing is written to disk and the -v output goes to stderr.

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

With -O, the contents of regular members are written to standard output
instead of being created on disk, like GNU tar. Other member types are
skipped, and -v output goes to standard error so it doesn't mix with the
contents.

Closes uutils#196
@ozenyunus35
ozenyunus35 requested a review from kaladron as a code owner October 14, 2026 12:32
@codspeed

codspeed Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

⚠️ 4 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 7 untouched benchmarks


Comparing ozenyunus35:to-stdout (60f77fb) with main (fb55fee)

Open in CodSpeed

@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.71429% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.88%. Comparing base (791ae26) to head (60f77fb).
⚠️ Report is 90 commits behind head on main.

Files with missing lines Patch % Lines
src/uu/tar/src/operations/extract.rs 85.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #403      +/-   ##
==========================================
+ Coverage   96.84%   97.88%   +1.03%     
==========================================
  Files          11       15       +4     
  Lines        1492     1893     +401     
  Branches       29       42      +13     
==========================================
+ Hits         1445     1853     +408     
+ Misses         46       39       -7     
  Partials        1        1              
Flag Coverage Δ
macos_latest 97.88% <95.71%> (+1.03%) ⬆️
ubuntu_latest 97.88% <95.71%> (+1.03%) ⬆️
windows_latest 0.00% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown

GNU Testsuite Comparison

Congrats! The gnu test tests/test 107/--to-stdout is no longer failing!

@github-actions

Copy link
Copy Markdown

GNU Testsuite Comparison

Congrats! The gnu test tests/test 107/--to-stdout is no longer failing!

Comment thread src/uu/tar/src/operations/extract.rs Outdated
Box::new(io::stdout().lock())
};
let mut out = BufWriter::new(status);
let mut data = BufWriter::new(io::stdout().lock());

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.

do we need to lock stdout a second time when to_stdout is false?
maybe an Option or just reuse out

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.

No, it's an Option now and only locked with -O.

Comment thread src/uu/tar/src/operations/extract.rs Outdated
// Like GNU tar, only regular files have contents to write.
if entry.header().entry_type().is_file() {
out.flush().map_err(TarError::Io)?;
io::copy(&mut entry, &mut data).map_err(|e| TarError::CannotExtract {

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.

could you please flush data after each member too?
with -xvOf a.tar 2>&1 all the names come out before all the contents, GNU interleaves them

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.

Done, data is flushed after each member.

Comment thread tests/by-util/test_tar.rs
at.write("dir/a.txt", "first\n");
at.write("dir/b.txt", "second\n");
ts.ucmd()
.args(&["-cf", "archive.tar", "dir/a.txt", "dir/b.txt"])

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 archive dir itself too and check that it isn't created with -O
this way the "only regular files" path is tested

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: it archives a directory, extracts it with -O and checks the directory isn't created.

}

out.flush().map_err(TarError::Io)?;
if let Some(data) = data.as_mut() {

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.

do we still need this? data is already flushed after each member

@github-actions

Copy link
Copy Markdown

GNU Testsuite Comparison

GNU test failed: tests/test 43/recurse. tests/test 43/recurse is passing on 'main'. Maybe you have to rebase?
Congrats! The gnu test tests/test 107/--to-stdout is no longer failing!

# Conflicts:
#	src/uu/tar/src/tar.rs
#	tests/by-util/test_tar.rs
@github-actions

Copy link
Copy Markdown

GNU Testsuite Comparison

Congrats! The gnu test tests/test 107/--to-stdout is no longer failing!

@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.

GNU tar compatibility: Add -O / --to-stdout

2 participants