There was a report that the change to quote output from env by default,
even if output is not a tty, caused some breakage:

https://github.com/coreutils/coreutils/issues/355

Note the usage described there is non-robust,
and seems rare (no cases on debian codesearch)
and can be avoided by adding QUOTING_STYLE=literal etc.

Also When reviewing more cases on debian codesearch
there were many cases that were made more robust
with the current behavior of quoting.

So I'm 50:50 on reverting with the attached.

I'll leave it distill for a while longer at least.

cheers,
Padraig
From 434bac960b6dc7c3a6a0c22b05a0876fd7144f30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Tue, 15 Sep 2026 20:26:28 +0100
Subject: [PATCH] env,printenv: only quote when outputting to terminals

To support albeit non-robust but existing use cases like:

  env | grep SPARK_JAVA_OPT_ | sort -t_ -k4 -n |
   sed 's/[^=]*=\(.*\)/\1/g' > java_opts.txt
  readarray -t SPARK_EXECUTOR_JAVA_OPTS < java_opts.txt
  ...
  CMD=("${JAVA_HOME}/bin/java" "${SPARK_EXECUTOR_JAVA_OPTS[@]}" ...)

* src/env.c (main): Restrict quoting to terminals.
* src/printenv.c (main): Likewise.
* tests/env/env.sh: Adjust accordingly.
* tests/misc/printenv.sh: Likewise.
* NEWS: Mention the change in behavior.

Link: https://github.com/coreutils/coreutils/issues/355
---
 NEWS                   |  7 +++++++
 src/env.c              |  2 +-
 src/printenv.c         |  2 +-
 tests/env/env.sh       | 31 +++++++------------------------
 tests/misc/printenv.sh | 40 ++++------------------------------------
 5 files changed, 20 insertions(+), 62 deletions(-)

diff --git a/NEWS b/NEWS
index b59f543ec..c92b09681 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,13 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Changes in behavior
+
+  'env' and 'printenv' now only quote printed environment variables honoring the
+  QUOTING_STYLE environment variable, when printing to a terminal.
+  In the previous release other outputs were quoted in POSIX shell compatible
+  format by default.
+
 
 * Noteworthy changes in release 9.12 (2026-09-14) [stable]
 
diff --git a/src/env.c b/src/env.c
index e646cba96..8fff89e72 100644
--- a/src/env.c
+++ b/src/env.c
@@ -1113,7 +1113,7 @@ main (int argc, char **argv)
 
   /* Get the value from QUOTING_STYLE before unsetting environment
      variables.  */
-  if (!opt_nul_terminate_output)
+  if (!opt_nul_terminate_output && isatty (STDOUT_FILENO))
     {
       int qs = getenv_quoting_style ();
       if (qs < 0)
diff --git a/src/printenv.c b/src/printenv.c
index dba87f373..00ca29f55 100644
--- a/src/printenv.c
+++ b/src/printenv.c
@@ -113,7 +113,7 @@ main (int argc, char **argv)
   bool quote_output = false;
   idx_t const n_args = argc - optind;
 
-  if (!opt_nul_terminate_output && (n_args <= 0 || isatty (STDOUT_FILENO)))
+  if (!opt_nul_terminate_output && isatty (STDOUT_FILENO))
     {
       int qs = getenv_quoting_style ();
       if (qs < 0)
diff --git a/tests/env/env.sh b/tests/env/env.sh
index be822e346..8853e0163 100755
--- a/tests/env/env.sh
+++ b/tests/env/env.sh
@@ -91,18 +91,14 @@ EOF
 compare exp out || fail=1
 
 # env shouldn't care what encoding name or value is
-cat <<\EOF >exp || framework_failure_
-NON_UTF8_TEST=''$'\240'
-EOF
+printf 'NON_UTF8_TEST=\240\n' > exp || framework_failure_
 env $(printf 'NON_UTF8_TEST=\240') env > all || fail=1
 grep '^NON_UTF8_TEST' all | LC_ALL=C sort > out || framework_failure_
 compare exp out || fail=1
 
-cat <<\EOF >exp || framework_failure_
-'NON_UTF8_TEST'$'\240'=1
-EOF
+printf 'NON_UTF8_TEST\240=1\n' > exp || framework_failure_
 env $(printf 'NON_UTF8_TEST\240=1') env > all || fail=1
-grep "^'NON_UTF8_TEST" all | LC_ALL=C sort > out || framework_failure_
+grep "^NON_UTF8_TEST" all | LC_ALL=C sort > out || framework_failure_
 compare exp out || fail=1
 
 # PATH modifications affect exec.
@@ -193,29 +189,16 @@ EOF
 compare err_exp err || fail=1
 done
 
-# QUOTING_STYLE affects redirected output.
-cat <<\EOF >exp-noargs-literal || framework_failure_
-a b=c d
-EOF
-cat <<\EOF >exp-noargs-shell || framework_failure_
-'a b'='c d'
-EOF
-tr "'" '"' <exp-noargs-shell >exp-noargs-c || framework_failure_
-for qs in literal shell c; do
+# QUOTING_STYLE does not affect redirected output.
+printf '%s\n' 'a b=c d' > exp || framework_failure_
+for qs in literal shell-always invalid; do
   env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \
     env >out-t 2>err || fail=1
   grep -vE '^["'"'"']?'\
 '(__CF_USER_TEXT_ENCODING|QUOTING_STYLE|(LD_ORIGIN_)?PATH)["'"'"']?=' \
     out-t >out || framework_failure_
-  compare exp-noargs-$qs out || fail=1
+  compare exp out || fail=1
   compare /dev/null err || fail=1
 done
 
-# Check the behavior with an invalid value for QUOTING_STYLE.
-printf 'env: ignoring invalid value of environment variable %s\n' \
-  "QUOTING_STYLE: 'invalid'" >exp || framework_failure_
-env QUOTING_STYLE=invalid env >out 2>err || fail=1
-grep '^QUOTING_STYLE=invalid$' out || fail=1
-compare exp err || fail=1
-
 Exit $fail
diff --git a/tests/misc/printenv.sh b/tests/misc/printenv.sh
index b8c3696c4..33ad6cc51 100755
--- a/tests/misc/printenv.sh
+++ b/tests/misc/printenv.sh
@@ -80,48 +80,16 @@ compare exp out || fail=1
 returns_ 1 env a=b=c printenv a=b > out || fail=1
 compare /dev/null out || fail=1
 
-# QUOTING_STYLE affects redirected output.
-cat <<\EOF >exp-noargs-literal || framework_failure_
-a b=c d
-EOF
-cat <<\EOF >exp-arg-literal || framework_failure_
-c d
-EOF
-cat <<\EOF >exp-args-literal || framework_failure_
-c d
-c d
-EOF
-cat <<\EOF >exp-noargs-shell || framework_failure_
-'a b'='c d'
-EOF
-cp exp-arg-literal exp-arg-shell &&
-cp exp-args-literal exp-args-shell || framework_failure_
-for t in noargs arg args; do
-  tr "'" '"' <exp-$t-shell >exp-$t-c || framework_failure_
-done
-for qs in literal shell c; do
+# QUOTING_STYLE does not affect redirected output.
+printf '%s\n' 'a b=c d' > exp || framework_failure_
+for qs in literal shell-always invalid; do
   env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \
     printenv >out-t 2>err || fail=1
   grep -vE '^["'"'"']?'\
 '(__CF_USER_TEXT_ENCODING|QUOTING_STYLE|(LD_ORIGIN_)?PATH)["'"'"']?=' \
     out-t >out || framework_failure_
-  compare exp-noargs-$qs out || fail=1
-  compare /dev/null err || fail=1
-  env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \
-    printenv 'a b' >out 2>err || fail=1
-  compare exp-arg-$qs out || fail=1
-  compare /dev/null err || fail=1
-  env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \
-    printenv 'a b' 'a b' >out 2>err || fail=1
-  compare exp-args-$qs out || fail=1
+  compare exp out || fail=1
   compare /dev/null err || fail=1
 done
 
-# Check the behavior with an invalid value for QUOTING_STYLE.
-printf 'printenv: ignoring invalid value of environment variable %s\n' \
-  "QUOTING_STYLE: 'invalid'" >exp || framework_failure_
-env QUOTING_STYLE=invalid printenv >out 2>err || fail=1
-grep '^QUOTING_STYLE=invalid$' out || fail=1
-compare exp err || fail=1
-
 Exit $fail
-- 
2.55.0

Reply via email to