Hi, The 'test' command has the following change in POSIX 2024 [1]:
Austin Group Defect 375 is applied, adding the pathname1 -ef pathname2, pathname1 -nt pathname2, pathname1 -ot pathname2, s1 > s2, and s1 < s2 primaries. The -ef, -nt, and -ot operators are already implement in Coreutils. This patch adds '>', '<' as documented [1]: s1 > s2 True if s1 collates after s2 in the current locale; otherwise, false. s1 < s2 True if s1 collates before s2 in the current locale; otherwise, false. They are sort of annoying since they have to be quoted for the shell to not interpret them as redirections. But now that they are standardized they should probably be implemented. :) Collin [1] https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.html
>From 2a76b314be161eb6f2e0915e84401e7e04a0ca4b Mon Sep 17 00:00:00 2001 From: Collin Funk <collin.fu...@gmail.com> Date: Fri, 1 Nov 2024 20:49:16 -0700 Subject: [PATCH] test: add string operators added by POSIX 2024 * src/test.c (binop): Recognize the ">" and "<" operators. (three_arguments): Likewise. (binary_operator): Implement the "<" and ">" operators. (usage): Add operators to --help output. * tests/test/test.pl (@Tests): Add functionality tests. * doc/coreutils.txt (test invocation, String tests): Document new operators. --- doc/coreutils.texi | 12 +++++++++++- src/test.c | 23 ++++++++++++++++++++--- tests/test/test.pl | 8 ++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 60a07b2ef..e016fdf26 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -13733,7 +13733,7 @@ @node test invocation * File type tests:: @code{-[bcdfhLpSt]} * Access permission tests:: @code{-[gkruwxOG]} * File characteristic tests:: @code{-e -s -nt -ot -ef} -* String tests:: @code{-z -n = == !=} +* String tests:: @code{-z -n = == != > <} * Numeric tests:: @code{-eq -ne -lt -le -gt -ge} * Connectives for test:: @code{! -a -o} @end menu @@ -13942,6 +13942,16 @@ @node String tests @cindex not-equal string check True if the strings are not equal. +@item @var{string1} > @var{string2} +@opindex > +@cindex greater-than string check +True if @var{string1} is greater than @var{string2} in the current locale. + +@item @var{string1} < @var{string2} +@opindex < +@cindex less-than string check +True if @var{string1} is less than @var{string2} in the current locale. + @end table diff --git a/src/test.c b/src/test.c index 5af924347..7d3a78879 100644 --- a/src/test.c +++ b/src/test.c @@ -173,7 +173,7 @@ static bool binop (char const *s) { return ((STREQ (s, "=")) || (STREQ (s, "!=")) || (STREQ (s, "==")) || - (STREQ (s, "-nt")) || + (STREQ (s, "-nt")) || (STREQ (s, ">")) || (STREQ (s, "<")) || (STREQ (s, "-ot")) || (STREQ (s, "-ef")) || (STREQ (s, "-eq")) || (STREQ (s, "-ne")) || (STREQ (s, "-lt")) || (STREQ (s, "-le")) || (STREQ (s, "-gt")) || (STREQ (s, "-ge"))); @@ -189,7 +189,7 @@ binop (char const *s) * '-t' int * '-'('z'|'n') string * string - * string ('!='|'=') string + * string ('!='|'='|>|<) string * <int> '-'(eq|ne|le|lt|ge|gt) <int> * file '-'(nt|ot|ef) file * '(' <expr> ')' @@ -371,6 +371,20 @@ binary_operator (bool l_is_l) return value; } + if (STREQ (argv[op], ">")) + { + bool value = strcoll (argv[pos], argv[pos + 2]) > 0; + pos += 3; + return value; + } + + if (STREQ (argv[op], "<")) + { + bool value = strcoll (argv[pos], argv[pos + 2]) < 0; + pos += 3; + return value; + } + /* Not reached. */ affirm (false); } @@ -615,7 +629,8 @@ three_arguments (void) value = one_argument (); advance (false); } - else if (STREQ (argv[pos + 1], "-a") || STREQ (argv[pos + 1], "-o")) + else if (STREQ (argv[pos + 1], "-a") || STREQ (argv[pos + 1], "-o") + || STREQ (argv[pos + 1], ">") || STREQ (argv[pos + 1], "<")) value = expr (); else test_syntax_error (_("%s: binary operator expected"), @@ -708,6 +723,8 @@ EXPRESSION is true or false and sets exit status. It is one of:\n\ -z STRING the length of STRING is zero\n\ STRING1 = STRING2 the strings are equal\n\ STRING1 != STRING2 the strings are not equal\n\ + STRING1 > STRING2 STRING1 is greater than STRING2 in the current locale\n\ + STRING1 < STRING2 STRING1 is less than STRING2 in the current locale\n\ "), stdout); fputs (_("\ \n\ diff --git a/tests/test/test.pl b/tests/test/test.pl index 0433461d8..e8509448b 100755 --- a/tests/test/test.pl +++ b/tests/test/test.pl @@ -185,6 +185,14 @@ my @Tests = ['paren-3', "'(' ')' ')'"], ['paren-4', "'(' ! ')'"], ['paren-5', "'(' -a ')'"], + + ['less-collate-1', "'a' '<' 'b'"], + ['less-collate-2', "'a' '<' 'a'", {EXIT=>1}], + ['less-collate-3', "'b' '<' 'a'", {EXIT=>1}], + + ['greater-collate-1', "'b' '>' 'a'"], + ['greater-collate-2', "'a' '>' 'a'", {EXIT=>1}], + ['greater-collate-3', "'a' '>' 'b'", {EXIT=>1}], ); @Tests = add_inverse_op_tests \@Tests; -- 2.47.0