You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Redirect after a list or pipeline attaches to the whole list instead of the last command #345
A pipeline does the same: a | b > f parses as a redirected_statement whose body is the whole pipeline.
Bash shows the redirect belongs to the last command. The first command's error still prints in both of these:
ls /nonexistent ||true2>/dev/null
ls /nonexistent | cat 2>/dev/null
A heredoc behaves the same way: in cd dir && python3 - <<'PY' the heredoc_redirect hangs on the list, not on python3.
This matters to tools that read the tree to learn what a command writes or silences. They would read git fetch && ls 2>/dev/null as silencing git's errors.
Seen on 0.25.1 through web-tree-sitter 0.27.0. The closest issue we found is #167, "pipeline nodes shouldn't nest", which is closed.
The over-extended redirected_statement is now the first member of the pipeline, so the tree says (foo && cat f > out) | head -80. Bash binds the pipe tighter than && and runs foo && (cat f > out | head -80):
And with the redirect on an earlier member rather than the last one it is also correct:
foo > o && cat f | head -80
(program
(list
(redirected_statement body: (command ...) redirect: (file_redirect ...))
(pipeline (command ...) (command ...))))
So the inversion needs three things together: an and-or list, a redirect on its last member, and a pipe after it. 2> behaves identically to > here, which matches bash — a redirect has no effect on pipeline shape.
Seen on tree-sitter-bash 0.25.1 with the Python binding 0.25.2.
Activity
fprochazka commentedon Sep 19, 2026
A pipe after the redirect makes this worse than misattribution — it changes pipeline membership.
The over-extended
redirected_statementis now the first member of the pipeline, so the tree says(foo && cat f > out) | head -80. Bash binds the pipe tighter than&&and runsfoo && (cat f > out | head -80):Nothing is printed. Grouped the other way,
wc -lwould run and print0.Without the redirect the same shape nests correctly:
And with the redirect on an earlier member rather than the last one it is also correct:
So the inversion needs three things together: an and-or list, a redirect on its last member, and a pipe after it.
2>behaves identically to>here, which matches bash — a redirect has no effect on pipeline shape.Seen on tree-sitter-bash 0.25.1 with the Python binding 0.25.2.
Attribute a redirect to the command it was written on