From: Pádraig Brady Date: Fri, 31 Jul 2026 16:35:52 +0000 (+0100) Subject: du: quote problematic names on tty X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d18b73bb688adadee5ed834c65e0a20e134ddf88;p=thirdparty%2Fcoreutils.git du: quote problematic names on tty * doc/coreutils.texi (readlink invocation): Mention $QUOTING_STYLE is significant. * src/du.c (main): Quote output when appropriate. * tests/du/basic.sh: Add a test case. * NEWS: Mention the improvement. --- diff --git a/NEWS b/NEWS index 2db6c99ae0..3a7b175e30 100644 --- a/NEWS +++ b/NEWS @@ -84,9 +84,9 @@ GNU coreutils NEWS -*- outline -*- 'install -C' will now avoid updating file metadata when the destination already has the appropriate ownership and permissions. - 'basename', 'readlink', and 'realpath' now quote output in shell-escape style - when standard output is a terminal. The QUOTING_STYLE environment variable - can be used to adjust or disable the quoting. + 'basename', 'du', 'readlink', and 'realpath' now quote output in shell-escape + style when standard output is a terminal. The QUOTING_STYLE environment + variable can be used to adjust or disable the quoting. 'ls -m' now quotes files names containing commas when appropriate, so users can better distinguish separating commas. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index b675b6345a..441b80c3c5 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -12436,6 +12436,11 @@ the argument being processed is on. @end table +When standard output is a terminal, file names are quoted using +the @samp{shell-escape} style. The environment variable +@env{QUOTING_STYLE} can select the quoting style. Valid quoting styles are: +@quotingStyles + Since @command{du} relies on information reported by the operating system, its output might not reflect the space consumed in the underlying devices. For example; diff --git a/src/du.c b/src/du.c index eefb24f05a..7c9c486f1c 100644 --- a/src/du.c +++ b/src/du.c @@ -26,7 +26,7 @@ #include #include #include -#include "argmatch.h" +#include "argmatch.h" /* argmatch($QUOTING_STYLE). */ #include "system.h" #include "argv-iter.h" #include "assure.h" @@ -135,6 +135,9 @@ static bool hash_all; /* If true, output the NUL byte instead of a newline at the end of each line. */ static bool opt_nul_terminate_output = false; +/* If true, quote output pathnames according to the selected quoting style. */ +static bool quote_output; + /* If true, print a grand total at the end. */ static bool print_grand_total = false; @@ -445,10 +448,11 @@ print_only_size (uintmax_t n_bytes) stdout); } -/* Print size (and optionally time) indicated by *PDUI, followed by STRING. */ +/* Print size (and optionally time) indicated by *PDUI, followed by STRING, + quoting STRING if QUOTE is true. */ static void -print_size (const struct duinfo *pdui, char const *string) +print_size (const struct duinfo *pdui, char const *string, bool quote) { print_only_size (opt_inodes ? pdui->inodes @@ -466,7 +470,7 @@ print_size (const struct duinfo *pdui, char const *string) } } putchar ('\t'); - fputs (string, stdout); + fputs (quote ? quoteN (string) : string, stdout); putchar (opt_nul_terminate_output ? '\0' : '\n'); if (fflush (stdout) < 0) write_error (); @@ -718,7 +722,7 @@ process_file (FTS *fts, FTSENT *ent) if (opt_threshold < 0 ? v <= -opt_threshold : v >= opt_threshold) - print_size (&dui_to_print, file); + print_size (&dui_to_print, file, quote_output); } return ok; @@ -983,6 +987,18 @@ main (int argc, char **argv) if (!ok) usage (EXIT_FAILURE); + if (!opt_nul_terminate_output && isatty (STDOUT_FILENO)) + { + int qs = getenv_quoting_style (); + if (qs < 0) + qs = shell_escape_quoting_style; + if (qs != literal_quoting_style) + { + set_quoting_style (NULL, qs); + quote_output = true; + } + } + if (opt_all && opt_summarize_only) { error (0, 0, _("cannot both summarize and show all entries")); @@ -1192,7 +1208,7 @@ main (int argc, char **argv) error (EXIT_FAILURE, 0, _("error reading %s"), quoteaf (files_from)); if (print_grand_total) - print_size (&tot_dui, _("total")); + print_size (&tot_dui, _("total"), false); return ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/du/basic.sh b/tests/du/basic.sh index 3bf74f712b..45567f71d7 100755 --- a/tests/du/basic.sh +++ b/tests/du/basic.sh @@ -28,6 +28,21 @@ printf '%*s' 257 make-sure-the-file-is-non-empty > a/b/F || framework_failure_ printf %4096s x > d/1 cp d/1 d/sub/2 +# QUOTING_STYLE does not affect redirected output. +touch 'q name' || framework_failure_ +printf '0\tq name\n' > exp || framework_failure_ +for style in literal shell-always invalid; do + QUOTING_STYLE="$style" du -b 'q name' > out 2> err || fail=1 + compare exp out || fail=1 + compare /dev/null err || fail=1 +done + +# --null disables quoting, and does not inspect QUOTING_STYLE. +QUOTING_STYLE=invalid du -0b 'q name' > out 2> err || fail=1 +printf '0\tq name\0' > exp || framework_failure_ +compare exp out || fail=1 +compare /dev/null err || fail=1 + B=$(stat --format=%B a/b/F)