ls(1): add a -v flag to sort naturally
Add a -v flag for ls which sorts entries following a natural ordering using strverscmp(3) (e.g. "bloem1 bloem9 bloem10" as opposed to "bloem1 bloem10 bloem9"). Update the manual page and add a test case. Reviewed by: pauamma, bcr Tested by: pstef Differential Revision: https://reviews.freebsd.org/D36407
This commit is contained in:
parent
595746df6f
commit
e2662256cd
14
bin/ls/cmp.c
14
bin/ls/cmp.c
@ -64,6 +64,20 @@ revnamecmp(const FTSENT *a, const FTSENT *b)
|
|||||||
return (strcoll(b->fts_name, a->fts_name));
|
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
|
int
|
||||||
modcmp(const FTSENT *a, const FTSENT *b)
|
modcmp(const FTSENT *a, const FTSENT *b)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,8 @@ int modcmp(const FTSENT *, const FTSENT *);
|
|||||||
int revmodcmp(const FTSENT *, const FTSENT *);
|
int revmodcmp(const FTSENT *, const FTSENT *);
|
||||||
int namecmp(const FTSENT *, const FTSENT *);
|
int namecmp(const FTSENT *, const FTSENT *);
|
||||||
int revnamecmp(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 statcmp(const FTSENT *, const FTSENT *);
|
||||||
int revstatcmp(const FTSENT *, const FTSENT *);
|
int revstatcmp(const FTSENT *, const FTSENT *);
|
||||||
int sizecmp(const FTSENT *, const FTSENT *);
|
int sizecmp(const FTSENT *, const FTSENT *);
|
||||||
|
22
bin/ls/ls.1
22
bin/ls/ls.1
@ -32,7 +32,7 @@
|
|||||||
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94
|
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd August 31, 2020
|
.Dd October 31, 2022
|
||||||
.Dt LS 1
|
.Dt LS 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -40,7 +40,7 @@
|
|||||||
.Nd list directory contents
|
.Nd list directory contents
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1\&,
|
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1\&,
|
||||||
.Op Fl -color Ns = Ns Ar when
|
.Op Fl -color Ns = Ns Ar when
|
||||||
.Op Fl D Ar format
|
.Op Fl D Ar format
|
||||||
.Op Ar
|
.Op Ar
|
||||||
@ -399,6 +399,15 @@ of the file for sorting
|
|||||||
.Pq Fl t
|
.Pq Fl t
|
||||||
or printing
|
or printing
|
||||||
.Pq Fl l .
|
.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
|
.It Fl w
|
||||||
Force raw printing of non-printable characters.
|
Force raw printing of non-printable characters.
|
||||||
This is the default
|
This is the default
|
||||||
@ -883,8 +892,10 @@ specification.
|
|||||||
.Xr sort 1 ,
|
.Xr sort 1 ,
|
||||||
.Xr xterm 1 Pq Pa ports/x11/xterm ,
|
.Xr xterm 1 Pq Pa ports/x11/xterm ,
|
||||||
.Xr localeconv 3 ,
|
.Xr localeconv 3 ,
|
||||||
|
.Xr strcoll 3 ,
|
||||||
.Xr strftime 3 ,
|
.Xr strftime 3 ,
|
||||||
.Xr strmode 3 ,
|
.Xr strmode 3 ,
|
||||||
|
.Xr strverscmp 3 ,
|
||||||
.Xr termcap 5 ,
|
.Xr termcap 5 ,
|
||||||
.Xr maclabel 7 ,
|
.Xr maclabel 7 ,
|
||||||
.Xr sticky 7 ,
|
.Xr sticky 7 ,
|
||||||
@ -902,7 +913,7 @@ utility conforms to
|
|||||||
and
|
and
|
||||||
.St -p1003.1-2008 .
|
.St -p1003.1-2008 .
|
||||||
The options
|
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
|
and
|
||||||
.Fl ,
|
.Fl ,
|
||||||
are non-standard extensions.
|
are non-standard extensions.
|
||||||
@ -918,6 +929,11 @@ An
|
|||||||
.Nm
|
.Nm
|
||||||
command appeared in
|
command appeared in
|
||||||
.At v1 .
|
.At v1 .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fl v
|
||||||
|
option was added in
|
||||||
|
.Fx 14.0 .
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
To maintain backward compatibility, the relationships between the many
|
To maintain backward compatibility, the relationships between the many
|
||||||
options are quite complex.
|
options are quite complex.
|
||||||
|
22
bin/ls/ls.c
22
bin/ls/ls.c
@ -136,6 +136,7 @@ static int f_numericonly; /* don't convert uid/gid to name */
|
|||||||
int f_octal_escape; /* like f_octal but use C escapes if possible */
|
int f_octal_escape; /* like f_octal but use C escapes if possible */
|
||||||
static int f_recursive; /* ls subdirectories also */
|
static int f_recursive; /* ls subdirectories also */
|
||||||
static int f_reversesort; /* reverse whatever sort is used */
|
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_samesort; /* sort time and name in same direction */
|
||||||
int f_sectime; /* print full time information */
|
int f_sectime; /* print full time information */
|
||||||
static int f_singlecol; /* use single column output */
|
static int f_singlecol; /* use single column output */
|
||||||
@ -275,7 +276,7 @@ main(int argc, char *argv[])
|
|||||||
colorflag = COLORFLAG_AUTO;
|
colorflag = COLORFLAG_AUTO;
|
||||||
#endif
|
#endif
|
||||||
while ((ch = getopt_long(argc, argv,
|
while ((ch = getopt_long(argc, argv,
|
||||||
"+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,", long_opts,
|
"+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuvwxy,", long_opts,
|
||||||
NULL)) != -1) {
|
NULL)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
/*
|
/*
|
||||||
@ -439,6 +440,9 @@ main(int argc, char *argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
f_size = 1;
|
f_size = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
f_verssort = 1;
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
f_nonprint = 0;
|
f_nonprint = 0;
|
||||||
f_octal = 0;
|
f_octal = 0;
|
||||||
@ -566,10 +570,12 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* Select a sort function. */
|
/* Select a sort function. */
|
||||||
if (f_reversesort) {
|
if (f_reversesort) {
|
||||||
if (!f_timesort && !f_sizesort)
|
if (f_sizesort)
|
||||||
sortfcn = revnamecmp;
|
|
||||||
else if (f_sizesort)
|
|
||||||
sortfcn = revsizecmp;
|
sortfcn = revsizecmp;
|
||||||
|
else if (f_verssort)
|
||||||
|
sortfcn = revverscmp;
|
||||||
|
else if (!f_timesort)
|
||||||
|
sortfcn = revnamecmp;
|
||||||
else if (f_accesstime)
|
else if (f_accesstime)
|
||||||
sortfcn = revacccmp;
|
sortfcn = revacccmp;
|
||||||
else if (f_birthtime)
|
else if (f_birthtime)
|
||||||
@ -579,10 +585,12 @@ main(int argc, char *argv[])
|
|||||||
else /* Use modification time. */
|
else /* Use modification time. */
|
||||||
sortfcn = revmodcmp;
|
sortfcn = revmodcmp;
|
||||||
} else {
|
} else {
|
||||||
if (!f_timesort && !f_sizesort)
|
if (f_sizesort)
|
||||||
sortfcn = namecmp;
|
|
||||||
else if (f_sizesort)
|
|
||||||
sortfcn = sizecmp;
|
sortfcn = sizecmp;
|
||||||
|
else if (f_verssort)
|
||||||
|
sortfcn = verscmp;
|
||||||
|
else if (!f_timesort)
|
||||||
|
sortfcn = namecmp;
|
||||||
else if (f_accesstime)
|
else if (f_accesstime)
|
||||||
sortfcn = acccmp;
|
sortfcn = acccmp;
|
||||||
else if (f_birthtime)
|
else if (f_birthtime)
|
||||||
|
@ -846,6 +846,20 @@ u_flag_body()
|
|||||||
atf_check -e empty -o match:'a\.file.*b\.file' -s exit:0 ls -Cu
|
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
|
atf_test_case x_flag
|
||||||
x_flag_head()
|
x_flag_head()
|
||||||
{
|
{
|
||||||
@ -960,6 +974,7 @@ atf_init_test_cases()
|
|||||||
atf_add_test_case s_flag
|
atf_add_test_case s_flag
|
||||||
atf_add_test_case t_flag
|
atf_add_test_case t_flag
|
||||||
atf_add_test_case u_flag
|
atf_add_test_case u_flag
|
||||||
|
atf_add_test_case v_flag
|
||||||
atf_add_test_case x_flag
|
atf_add_test_case x_flag
|
||||||
atf_add_test_case y_flag
|
atf_add_test_case y_flag
|
||||||
atf_add_test_case 1_flag
|
atf_add_test_case 1_flag
|
||||||
|
@ -227,9 +227,9 @@ usage(void)
|
|||||||
{
|
{
|
||||||
(void)fprintf(stderr,
|
(void)fprintf(stderr,
|
||||||
#ifdef COLORLS
|
#ifdef COLORLS
|
||||||
"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [--color=when] [-D format]"
|
"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [--color=when] [-D format]"
|
||||||
#else
|
#else
|
||||||
"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
|
"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [-D format]"
|
||||||
#endif
|
#endif
|
||||||
" [file ...]\n");
|
" [file ...]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user