From 2af174513ea95f0b636fe206b33ee88ef1dc5bdd Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Mon, 17 Feb 2020 08:52:41 +0100 Subject: [PATCH] Reallow "2>>&1" as a redirection Appending to an fd doesn't really make sense, but we allowed the syntax previously and it was actually used. It's not too harmful to allow it, so let's just do that again. For the record: Zsh also allows it, bash doesn't. Fixes #6614 (cherry picked from commit aba900a71f5313990f96ccf20e6751e4a70b8fde) --- src/tokenizer.cpp | 5 +++-- tests/checks/redirect.fish | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index d568e81bd..992f7b6b3 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -362,6 +362,7 @@ maybe_t pipe_or_redir_t::from_string(const wchar_t *buff) { } case L'>': { consume(L'>'); + if (try_consume(L'>')) result.mode = redirection_mode_t::append; if (try_consume(L'|')) { // Note we differ from bash here. // Consider `echo foo 2>| bar` @@ -374,6 +375,7 @@ maybe_t pipe_or_redir_t::from_string(const wchar_t *buff) { : STDOUT_FILENO; // like >| } else if (try_consume(L'&')) { // This is a redirection to an fd. + // Note that we allow ">>&", but it's still just writing to the fd - "appending" to it doesn't make sense. result.mode = redirection_mode_t::fd; result.fd = has_fd ? parse_fd(fd_start, fd_end) // like 1>&2 : STDOUT_FILENO; // like >&2 @@ -381,11 +383,10 @@ maybe_t pipe_or_redir_t::from_string(const wchar_t *buff) { // This is a redirection to a file. result.fd = has_fd ? parse_fd(fd_start, fd_end) // like 1> file.txt : STDOUT_FILENO; // like > file.txt + if (result.mode != redirection_mode_t::append) result.mode = redirection_mode_t::overwrite; // Note 'echo abc >>? file' is valid: it means append and noclobber. // But here "noclobber" means the file must not exist, so appending // can be ignored. - result.mode = redirection_mode_t::overwrite; - if (try_consume(L'>')) result.mode = redirection_mode_t::append; if (try_consume(L'?')) result.mode = redirection_mode_t::noclob; } break; diff --git a/tests/checks/redirect.fish b/tests/checks/redirect.fish index 14bc3298c..d1cd61772 100644 --- a/tests/checks/redirect.fish +++ b/tests/checks/redirect.fish @@ -8,6 +8,11 @@ end outnerr 0 &| count #CHECK: 2 + +outnerr appendfd 2>>&1 +#CHECK: out appendfd +#CHECK: err appendfd + set -l tmpdir (mktemp -d) outnerr overwrite &>$tmpdir/file.txt cat $tmpdir/file.txt