summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/coreutils.texi10
-rw-r--r--src/stat.c41
-rwxr-xr-xtests/misc/stat-fmt.sh15
4 files changed, 62 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 9548de885..844e23332 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,9 @@ GNU coreutils NEWS -*- outline -*-
tail -f uses polling for "prl_fs" and "smb2", inotify for "m1fs",
and attempts inotify for "wslfs".
+ stat --format=%N for quoting file names now honors the
+ same QUOTING_STYLE environment variable values as ls.
+
** New Features
date now accepts the --debug option, to annotate the parsed date string,
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 95419b44e..927e552ab 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -7724,6 +7724,7 @@ Use style @var{word} to quote file names and other strings that may
contain arbitrary characters. The @var{word} should
be one of the following:
+@macro quotingStyles
@table @samp
@item literal
Output strings as-is; this is the same as the @option{-N} or
@@ -7761,6 +7762,8 @@ surrounding quotation marks appropriate for the locale, and quote
@t{'like this'} instead of @t{"like
this"} in the default C locale. This looks nicer on many displays.
@end table
+@end macro
+@quotingStyles
You can specify the default value of the @option{--quoting-style} option
with the environment variable @env{QUOTING_STYLE}@. If that environment
@@ -11775,7 +11778,7 @@ The valid @var{format} directives for files with @option{--format} and
@item %i - Inode number
@item %m - Mount point (See note below)
@item %n - File name
-@item %N - Quoted file name with dereference if symbolic link
+@item %N - Quoted file name with dereference if symbolic link (see below)
@item %o - Optimal I/O transfer size hint
@item %s - Total size, in bytes
@item %t - Major device type in hex (see below)
@@ -11797,6 +11800,11 @@ to control the zero padding of the output with the @samp{#} and @samp{0}
printf flags. For example to pad to at least 3 wide while making larger
numbers unambiguously octal, you can use @samp{%#03a}.
+The @samp{%N} format can be set with the environment variable
+@env{QUOTING_STYLE}@. If that environment variable is not set,
+the default value is @samp{shell-escape}. Valid quoting styles are:
+@quotingStyles
+
The @samp{%t} and @samp{%T} formats operate on the st_rdev member of
the stat(2) structure, and are only defined for character and block
special files. On some systems or file types, st_rdev may be used to
diff --git a/src/stat.c b/src/stat.c
index 53a6cb7bb..a43eca4d2 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -59,6 +59,7 @@
#include "system.h"
#include "areadlink.h"
+#include "argmatch.h"
#include "die.h"
#include "error.h"
#include "file-type.h"
@@ -997,6 +998,32 @@ neg_to_zero (struct timespec ts)
return z;
}
+/* Set the quoting style default if the environment variable
+ QUOTING_STYLE is set. */
+
+static void
+getenv_quoting_style (void)
+{
+ char const *q_style = getenv ("QUOTING_STYLE");
+ if (q_style)
+ {
+ int i = ARGMATCH (q_style, quoting_style_args, quoting_style_vals);
+ if (0 <= i)
+ set_quoting_style (NULL, quoting_style_vals[i]);
+ else
+ {
+ set_quoting_style (NULL, shell_escape_always_quoting_style);
+ error (0, 0, _("ignoring invalid value of environment "
+ "variable QUOTING_STYLE: %s"), quote (q_style));
+ }
+ }
+ else
+ set_quoting_style (NULL, shell_escape_always_quoting_style);
+}
+
+/* Equivalent to quotearg(), but explicit to avoid syntax checks. */
+#define quoteN(x) quotearg_style (get_quoting_style (NULL), x)
+
/* Print stat info. Return zero upon success, nonzero upon failure. */
static bool
print_stat (char *pformat, size_t prefix_len, unsigned int m,
@@ -1013,7 +1040,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
out_string (pformat, prefix_len, filename);
break;
case 'N':
- out_string (pformat, prefix_len, quoteaf (filename));
+ out_string (pformat, prefix_len, quoteN (filename));
if (S_ISLNK (statbuf->st_mode))
{
char *linkname = areadlink_with_size (filename, statbuf->st_size);
@@ -1024,7 +1051,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m,
return true;
}
printf (" -> ");
- out_string (pformat, prefix_len, quoteaf (linkname));
+ out_string (pformat, prefix_len, quoteN (linkname));
free (linkname);
}
break;
@@ -1602,11 +1629,15 @@ main (int argc, char *argv[])
}
if (format)
- format2 = format;
+ {
+ if (strstr (format, "%N"))
+ getenv_quoting_style ();
+ format2 = format;
+ }
else
{
- format = default_format (fs, terse, false);
- format2 = default_format (fs, terse, true);
+ format = default_format (fs, terse, /* device= */ false);
+ format2 = default_format (fs, terse, /* device= */ true);
}
for (i = optind; i < argc; i++)
diff --git a/tests/misc/stat-fmt.sh b/tests/misc/stat-fmt.sh
index baa7ca775..1245ddb9e 100755
--- a/tests/misc/stat-fmt.sh
+++ b/tests/misc/stat-fmt.sh
@@ -20,11 +20,24 @@
print_ver_ stat
-
+# ensure that stat properly handles a format string ending with %
for i in $(seq 50); do
fmt=$(printf "%${i}s" %)
out=$(stat --form="$fmt" .)
test "$out" = "$fmt" || fail=1
done
+# ensure QUOTING_STYLE is honored by %N
+touch "'" || framework_failure_
+# Default since v8.25
+stat -c%N \' >> out || fail=1
+# Default before v8.25
+QUOTING_STYLE=locale stat -c%N \' >> out || fail=1
+cat <<\EOF >exp
+"'"
+'\''
+EOF
+compare exp out || fail=1
+
+
Exit $fail