From 410f48719c378c1812ecd26d5a80a5f1144e2222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?=
Date: Tue, 15 Sep 2026 20:26:28 +0100
Subject: [PATCH 1/2] 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.
* doc/coreutils.texi: Likewise.
* NEWS: Mention the change in behavior.
Link: https://github.com/coreutils/coreutils/issues/355
---
NEWS | 6 ++++++
doc/coreutils.texi | 16 ++++++----------
src/env.c | 2 +-
src/printenv.c | 2 +-
tests/env/env.sh | 31 +++++++------------------------
tests/misc/printenv.sh | 40 ++++------------------------------------
6 files changed, 25 insertions(+), 72 deletions(-)
diff --git a/NEWS b/NEWS
index b59f543ec..1b0618576 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU coreutils NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Changes in behavior
+
+ 'env' and 'printenv' now quote printed environment variables only when
+ outputting to a terminal. The previous release enabled this for all
+ outputs by default, requiring setting QUOTING_STYLE=literal to disable.
+
* Noteworthy changes in release 9.12 (2026-09-14) [stable]
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index b769e64c1..9d7888511 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -15519,13 +15519,9 @@ The program accepts the following option. Also see @ref{Common options}.
@end table
-If no @var{variable}s are specified, @command{printenv} quotes
+If standard output is a terminal @command{printenv} quotes
environment variables and their values using the @samp{shell-escape}
-style. If @var{variable}s are specified, @command{printenv} only quotes
-their values using the @samp{shell-escape} style if standard output is a
-terminal.
-
-The environment variable @env{QUOTING_STYLE}
+style by default. The environment variable @env{QUOTING_STYLE}
specifies the quoting style. Valid quoting styles are:
@quotingStyles
@@ -17497,10 +17493,10 @@ If no command name is specified following the environment
specifications, the resulting environment is printed. This is like
specifying the @command{printenv} program.
-The printed environment variables and their values are quoted using the
-@samp{shell-escape} style. The environment variable
-@env{QUOTING_STYLE} specifies the quoting style. Valid quoting styles
-are:
+If standard output is a terminal, the printed environment variables
+and their values are quoted using the @samp{shell-escape} style by default.
+The environment variable @env{QUOTING_STYLE} specifies the quoting style.
+Valid quoting styles are:
@quotingStyles
For some examples, suppose the environment passed to @command{env}
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 "'" '"'