diff --git a/bin/ls/cmp.c b/bin/ls/cmp.c --- a/bin/ls/cmp.c +++ b/bin/ls/cmp.c @@ -64,6 +64,20 @@ return (strcoll(b->fts_name, a->fts_name)); } +int +verscmp(const FTSENT *a, const FTSENT *b) +{ + + return (strverscmp(a->fts_name, b->fts_name)); +} + +int +revverscmp(const FTSENT *a, const FTSENT *b) +{ + + return (strverscmp(b->fts_name, a->fts_name)); +} + int modcmp(const FTSENT *a, const FTSENT *b) { diff --git a/bin/ls/extern.h b/bin/ls/extern.h --- a/bin/ls/extern.h +++ b/bin/ls/extern.h @@ -42,6 +42,8 @@ int revmodcmp(const FTSENT *, const FTSENT *); int namecmp(const FTSENT *, const FTSENT *); int revnamecmp(const FTSENT *, const FTSENT *); +int verscmp(const FTSENT *, const FTSENT *); +int revverscmp(const FTSENT *, const FTSENT *); int statcmp(const FTSENT *, const FTSENT *); int revstatcmp(const FTSENT *, const FTSENT *); int sizecmp(const FTSENT *, const FTSENT *); diff --git a/bin/ls/ls.1 b/bin/ls/ls.1 --- a/bin/ls/ls.1 +++ b/bin/ls/ls.1 @@ -32,7 +32,7 @@ .\" @(#)ls.1 8.7 (Berkeley) 7/29/94 .\" $FreeBSD$ .\" -.Dd August 31, 2020 +.Dd July 11, 2022 .Dt LS 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Nd list directory contents .Sh SYNOPSIS .Nm -.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1\&, +.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1\&, .Op Fl -color Ns = Ns Ar when .Op Fl D Ar format .Op Ar @@ -127,8 +127,7 @@ after each whiteout, and a vertical bar .Pq Ql \&| -after each that is a -.Tn FIFO . +after each that is a FIFO. .It Fl G Enable colorized output. This option is equivalent to defining @@ -205,9 +204,7 @@ .It Fl b As .Fl B , -but use -.Tn C -escape codes whenever possible. +but use C escape codes whenever possible. This option is not defined in .St -p1003.1-2008 . .It Fl c @@ -229,9 +226,7 @@ .Ev TERM is unset or set to an invalid terminal, then .Nm -will fall back to explicit -.Tn ANSI -escape sequences without the help of +will fall back to explicit ANSI escape sequences without the help of .Xr termcap 5 . .Cm always is the default if @@ -399,6 +394,15 @@ .Pq Fl t or printing .Pq Fl l . +.It Fl v +Sort following a natural ordering, using +.Xr strverscmp 3 +instead of +.Xr strcoll 3 +as the comparison function. +E.g., files lexicographically ordered +"bloem1", "bloem10", and "bloem9" would instead be ordered +"bloem1", "bloem9", and "bloem10", as one would perhaps expect. .It Fl w Force raw printing of non-printable characters. This is the default @@ -563,7 +567,7 @@ .It Sy l Symbolic link. .It Sy p -.Tn FIFO . +FIFO. .It Sy s Socket. .It Sy w @@ -662,9 +666,7 @@ .Sx The Long Format subsection for more information. .It Ev CLICOLOR -Use -.Tn ANSI -color sequences to distinguish file types. +Use ANSI color sequences to distinguish file types. See .Ev LSCOLORS below. @@ -783,9 +785,7 @@ default foreground or background, with an underline or bold .El .Pp -Note that the above are standard -.Tn ANSI -colors. +Note that the above are standard ANSI colors. The actual display may differ depending on the color capabilities of the terminal in use. .Pp @@ -883,8 +883,10 @@ .Xr sort 1 , .Xr xterm 1 Pq Pa ports/x11/xterm , .Xr localeconv 3 , +.Xr strcoll 3 , .Xr strftime 3 , .Xr strmode 3 , +.Xr strverscmp 3 , .Xr termcap 5 , .Xr maclabel 7 , .Xr sticky 7 , @@ -902,15 +904,13 @@ and .St -p1003.1-2008 . The options -.Fl B , D , G , I , T , U , W , Z , b , h , w , y +.Fl B , D , G , I , T , U , W , Z , b , h , v , w , y and .Fl , are non-standard extensions. .Pp -The ACL support is compatible with -.Tn IEEE -Std\~1003.2c -.Pq Dq Tn POSIX Ns .2c +The ACL support is compatible with IEEE Std\~1003.2c +.Pq Dq POSIX Ns .2c Draft\~17 (withdrawn). .Sh HISTORY @@ -918,6 +918,11 @@ .Nm command appeared in .At v1 . +.Pp +The +.Fl v +option was added in +.Fx 14.0 . .Sh BUGS To maintain backward compatibility, the relationships between the many options are quite complex. diff --git a/bin/ls/ls.c b/bin/ls/ls.c --- a/bin/ls/ls.c +++ b/bin/ls/ls.c @@ -136,6 +136,7 @@ int f_octal_escape; /* like f_octal but use C escapes if possible */ static int f_recursive; /* ls subdirectories also */ static int f_reversesort; /* reverse whatever sort is used */ +static int f_verssort; /* sort names using strverscmp(3) rather than strcoll(3) */ int f_samesort; /* sort time and name in same direction */ int f_sectime; /* print full time information */ static int f_singlecol; /* use single column output */ @@ -275,7 +276,7 @@ colorflag = COLORFLAG_AUTO; #endif while ((ch = getopt_long(argc, argv, - "+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,", long_opts, + "+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuvwxy,", long_opts, NULL)) != -1) { switch (ch) { /* @@ -439,6 +440,9 @@ case 's': f_size = 1; break; + case 'v': + f_verssort = 1; + break; case 'w': f_nonprint = 0; f_octal = 0; @@ -566,10 +570,12 @@ } /* Select a sort function. */ if (f_reversesort) { - if (!f_timesort && !f_sizesort) - sortfcn = revnamecmp; - else if (f_sizesort) + if (f_sizesort) sortfcn = revsizecmp; + else if (f_verssort) + sortfcn = revverscmp; + else if (!f_timesort) + sortfcn = revnamecmp; else if (f_accesstime) sortfcn = revacccmp; else if (f_birthtime) @@ -579,10 +585,12 @@ else /* Use modification time. */ sortfcn = revmodcmp; } else { - if (!f_timesort && !f_sizesort) - sortfcn = namecmp; - else if (f_sizesort) + if (f_sizesort) sortfcn = sizecmp; + else if (f_verssort) + sortfcn = verscmp; + else if (!f_timesort) + sortfcn = namecmp; else if (f_accesstime) sortfcn = acccmp; else if (f_birthtime) diff --git a/bin/ls/tests/ls_tests.sh b/bin/ls/tests/ls_tests.sh --- a/bin/ls/tests/ls_tests.sh +++ b/bin/ls/tests/ls_tests.sh @@ -846,6 +846,20 @@ atf_check -e empty -o match:'a\.file.*b\.file' -s exit:0 ls -Cu } +atf_test_case v_flag +v_flag_head() +{ + atf_set "descr" "Verify that the output from ls -v sorts based on strverscmp(3)" +} + +v_flag_body() +{ + create_test_dir + + atf_check -e empty -o empty -s exit:0 touch 000 00 01 010 09 0 1 9 10 + atf_check -e empty -o match:"000.00.01.010.09.0.1.9.10" -s exit:0 sh -c 'ls -Cv' +} + atf_test_case x_flag x_flag_head() { @@ -960,6 +974,7 @@ atf_add_test_case s_flag atf_add_test_case t_flag atf_add_test_case u_flag + atf_add_test_case v_flag atf_add_test_case x_flag atf_add_test_case y_flag atf_add_test_case 1_flag diff --git a/bin/ls/util.c b/bin/ls/util.c --- a/bin/ls/util.c +++ b/bin/ls/util.c @@ -227,9 +227,9 @@ { (void)fprintf(stderr, #ifdef COLORLS - "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [--color=when] [-D format]" + "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [--color=when] [-D format]" #else - "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" + "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [-D format]" #endif " [file ...]\n"); exit(1);