diff --git a/src/builtin_echo.cpp b/src/builtin_echo.cpp index 55051f689..e380f63ed 100644 --- a/src/builtin_echo.cpp +++ b/src/builtin_echo.cpp @@ -207,16 +207,19 @@ maybe_t builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **arg bool continue_output = true; const wchar_t *const *args_to_echo = argv + optind; + // We buffer output so we can write in one go, + // this matters when writing to an fd. + wcstring out; for (size_t idx = 0; continue_output && args_to_echo[idx] != nullptr; idx++) { if (opts.print_spaces && idx > 0) { - streams.out.push_back(' '); + out.push_back(' '); } const wchar_t *str = args_to_echo[idx]; for (size_t j = 0; continue_output && str[j]; j++) { if (!opts.interpret_special_chars || str[j] != L'\\') { // Not an escape. - streams.out.push_back(str[j]); + out.push_back(str[j]); } else { // Most escapes consume one character in addition to the backslash; the numeric // sequences may consume more, while an unrecognized escape sequence consumes none. @@ -286,13 +289,18 @@ maybe_t builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **arg j += consumed; if (continue_output) { - streams.out.push_back(wc); + out.push_back(wc); } } } } if (opts.print_newline && continue_output) { - streams.out.push_back('\n'); + out.push_back('\n'); } + + if (!out.empty()) { + streams.out.append(out); + } + return STATUS_CMD_OK; }