Redirections are applied from left to right. Duplicating stderr from stdout copies its current destination; a later stdout redirection does not retroactively move that stderr destination.
Reproduce the behavior safely
Run this self-contained fixture in an empty temporary directory, separate from your project. Shell examples create only named fixture files there. JavaScript examples use local values and send no network requests.
emit() { printf 'out\n'; printf 'err\n' >&2; }
emit > both.txt 2>&1
{ emit 2>&1 > only-out.txt; } > captured.txt
printf 'both: '; tr '\n' ',' < both.txt; printf '\n'
printf 'only stdout: '; cat only-out.txt
printf 'earlier stdout destination: '; cat captured.txt
test "$(cat only-out.txt)" = out
test "$(cat captured.txt)" = err
test "$(wc -l < both.txt | tr -d ' ')" = 2Observed local output
both: out,err,
only stdout: out
earlier stdout destination: errWhy the result changes
In the first command, stdout points at both.txt before stderr is duplicated, so both streams reach that file. In the second, stderr first copies the enclosing group output destination, captured.txt. Stdout then moves to only-out.txt. The fixture supplies that outer destination explicitly so the otherwise terminal-bound error can be inspected as data.
Choose and verify the correction
Write down descriptors one and two and update their destinations in command order. Use command >log 2>&1 when both should share the opened log. Use separate redirections when each stream needs a separate destination. Choose append versus overwrite deliberately: the fixture overwrites only files in an empty temporary directory. Inspect real wrapper, pipeline and group redirections before assuming the short command is the whole routing configuration.
Limits and next checks
Descriptor routing does not guarantee chronological ordering of independently buffered application output. Adding tee or process substitution introduces more processes and their own completion and buffering rules. This guide does not solve multi-stream chronological logging. It explains the earlier destination boundary that must be correct before that separate problem is investigated.
Related: A Bash Script Exits Zero After Failed Checks: Preserve and Aggregate Status.
Isolated fixture executed on macOS on November 10, 2026 (KST), with GNU bash, version 3.2.57(1)-release (arm64-apple-darwin26). The observed output verifies this example, not every application or runtime.