Changes made:
- Consistent formatting of the labels
- Improved regression test
thanks,
Arun
---
doc/coreutils.texi | 7 +++++
src/uname.c | 59 ++++++++++++++++++++++++++-----------
tests/local.mk | 1 +
tests/misc/uname-labeled.sh | 44 +++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 18 deletions(-)
create mode 100755 tests/misc/uname-labeled.sh
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 5cc831f84..1ddc1d101 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16862,6 +16862,13 @@ The program accepts the following options.
Also see @ref{Common options}.
Print all of the below information, except omit the processor type
and the hardware platform name if they are unknown.
+@optItem{uname,-A,}
+@optItemx{uname,--all-labeled,}
+Print all of the below information in a vertical, labeled format:
+@var{label} : @var{value}.
+Like @option{-a}, the processor type and hardware platform name are omitted
+if they are unknown.
+
@optItem{uname,-i,}
@optItemx{uname,--hardware-platform,}
@cindex implementation, hardware
diff --git a/src/uname.c b/src/uname.c
index 5f7a35dd6..d41dabe49 100644
--- a/src/uname.c
+++ b/src/uname.c
@@ -79,9 +79,12 @@
/* Operating system. */
#define PRINT_OPERATING_SYSTEM 128
+static bool labeled = false;
+
static struct option const uname_long_options[] =
{
{"all", no_argument, NULL, 'a'},
+ {"all-labeled", no_argument, NULL, 'A'},
{"kernel-name", no_argument, NULL, 's'},
{"sysname", no_argument, NULL, 's'}, /* Obsolescent. */
{"nodename", no_argument, NULL, 'n'},
@@ -122,6 +125,10 @@ Print certain system information. With no OPTION,
same as -s.\n\
oputs (_("\
-a, --all print all information, in the following
order,\n\
except omit -p and -i if unknown\n\
+"));
+ oputs (_("\
+ -A, --all-labeled print all information, one labeled field per
line,\n\
+ except omit -p and -i if unknown\n\
"));
oputs (_("\
-s, --kernel-name print the kernel name\n\
@@ -167,13 +174,20 @@ Print machine architecture.\n\
printed. */
static void
-print_element (char const *element)
+print_element (char const *element, char const *label)
{
- static bool printed;
- if (printed)
- putchar (' ');
- printed = true;
- fputs (element, stdout);
+ if (labeled)
+ {
+ printf ("%s: %s\n", label, element);
+ }
+ else
+ {
+ static bool printed;
+ if (printed)
+ putchar (' ');
+ printed = true;
+ fputs (element, stdout);
+ }
}
/* Print ELEMENT, preceded by a space if something has already been
@@ -181,7 +195,9 @@ print_element (char const *element)
value instead of ELEMENT. */
static void
-print_element_env (char const *element, MAYBE_UNUSED char const *envvar)
+print_element_env (char const *element,
+ MAYBE_UNUSED char const *envvar,
+ char const *label)
{
#ifdef __APPLE__
if (envvar)
@@ -191,7 +207,7 @@ print_element_env (char const *element, MAYBE_UNUSED
char const *envvar)
element = val;
}
#endif
- print_element (element);
+ print_element (element, label);
}
@@ -224,7 +240,7 @@ decode_switches (int argc, char **argv)
}
else
{
- while ((c = getopt_long (argc, argv, "asnrvmpio",
+ while ((c = getopt_long (argc, argv, "asnrvmpioA",
uname_long_options, NULL))
!= -1)
{
@@ -232,6 +248,12 @@ decode_switches (int argc, char **argv)
{
case 'a':
toprint = UINT_MAX;
+ labeled = false;
+ break;
+
+ case 'A':
+ toprint = UINT_MAX;
+ labeled = true;
break;
case 's':
@@ -316,15 +338,15 @@ main (int argc, char **argv)
error (EXIT_FAILURE, errno, _("cannot get system name"));
if (toprint & PRINT_KERNEL_NAME)
- print_element_env (name.sysname, "UNAME_SYSNAME");
+ print_element_env (name.sysname, "UNAME_SYSNAME", _("Kernel
name"));
if (toprint & PRINT_NODENAME)
- print_element_env (name.nodename, "UNAME_NODENAME");
+ print_element_env (name.nodename, "UNAME_NODENAME", _("Node
name"));
if (toprint & PRINT_KERNEL_RELEASE)
- print_element_env (name.release, "UNAME_RELEASE");
+ print_element_env (name.release, "UNAME_RELEASE", _("Kernel
release"));
if (toprint & PRINT_KERNEL_VERSION)
- print_element_env (name.version, "UNAME_VERSION");
+ print_element_env (name.version, "UNAME_VERSION", _("Kernel
version"));
if (toprint & PRINT_MACHINE)
- print_element_env (name.machine, "UNAME_MACHINE");
+ print_element_env (name.machine, "UNAME_MACHINE", _("Machine"));
}
if (toprint & PRINT_PROCESSOR)
@@ -358,7 +380,7 @@ main (int argc, char **argv)
}
#endif
if (! (toprint == UINT_MAX && element == unknown))
- print_element (element);
+ print_element (element, _("Processor"));
}
if (toprint & PRINT_HARDWARE_PLATFORM)
@@ -383,13 +405,14 @@ main (int argc, char **argv)
}
#endif
if (! (toprint == UINT_MAX && element == unknown))
- print_element (element);
+ print_element (element, _("Hardware platform"));
}
if (toprint & PRINT_OPERATING_SYSTEM)
- print_element (HOST_OPERATING_SYSTEM);
+ print_element (HOST_OPERATING_SYSTEM, _("Operating system"));
- putchar ('\n');
+ if (!labeled)
+ putchar ('\n');
return EXIT_SUCCESS;
}
diff --git a/tests/local.mk b/tests/local.mk
index e2afbe134..7817edccf 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -290,6 +290,7 @@ all_tests = \
tests/mktemp/mktemp.pl \
tests/mktemp/write-error.sh \
tests/misc/arch.sh \
+ tests/misc/uname-labeled.sh \
tests/pr/bounded-memory.sh \
tests/pr/options.sh \
tests/pr/pr-tests.pl \
diff --git a/tests/misc/uname-labeled.sh b/tests/misc/uname-labeled.sh
new file mode 100755
index 000000000..52751753d
--- /dev/null
+++ b/tests/misc/uname-labeled.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Test -A / --all-labeled option of uname
+
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ uname
+
+# Test basic -A / --all-labeled functionality
+uname -A > out || fail=1
+uname --all-labeled > out_long || fail=1
+compare out out_long || fail=1
+
+# Check that the output format has labels and values
+grep "^Kernel name: " out || fail=1
+grep "^Node name: " out || fail=1
+grep "^Kernel release: " out || fail=1
+grep "^Kernel version: " out || fail=1
+grep "^Machine: " out || fail=1
+# processor and hardware-platform may be omitted if unknown
+grep "^Operating system: " out || fail=1
+
+# Ensure that standard uname output (e.g. uname -a) is unchanged
+uname -a > out_std || fail=1
+# out_std must be a single line and not contain the labels
+[ $(wc -l < out_std) -eq 1 ] || fail=1
+grep -F "Kernel name:" out_std && fail=1
+grep -F "Node name:" out_std && fail=1
+grep -F "Kernel release:" out_std && fail=1
+
+Exit $fail
--
2.54.0
On 7/14/26 17:09, Pádraig Brady wrote:
In general I think the proposal is useful.
On 14/07/2026 10:36, Arun Bhattacharya wrote:
+# Check that the output format has labels and values
+grep "^kernel name : " out || fail=1
+grep "^nodename : " out || fail=1
+grep "^kernel-release : " out || fail=1
+grep "^kernel-version : " out || fail=1
+grep "^machine : " out || fail=1
+# processor and hardware-platform may be omitted if unknown
+grep "^operating-system : " out || fail=1
I'd keep the label formats consistent.
There are 3 different formats above,
with spaces, no spaces, hyphens.
Also I'd avoid a space before the :
To be more consistent with other coreutils I'd use:
Kernel name: ...
Node name: ...
Kernel release: ...
...
+# Ensure that standard uname output (e.g. uname -a) is unchanged
+uname -a > out_std || fail=1
+# out_std should not contain " : "
+if grep " : " out_std; then
+ fail=1
+fi
That seems a little brittle as " : "
could be part of a version string etc.
thanks,
Padraig