git: 8b92977857f8 - main - ls: implement --group-directories-first for compatibility with GNU ls
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 16 Jan 2025 16:03:53 UTC
The branch main has been updated by pstef:
URL: https://cgit.FreeBSD.org/src/commit/?id=8b92977857f8acaa539c21800b024edea9eee8b4
commit 8b92977857f8acaa539c21800b024edea9eee8b4
Author: Piotr Paweł Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2025-01-06 21:26:14 +0000
Commit: Piotr Paweł Stefaniak <pstef@FreeBSD.org>
CommitDate: 2025-01-16 16:00:17 +0000
ls: implement --group-directories-first for compatibility with GNU ls
Also implement --group-directories which takes a parameter.
"first" is equivalent to --group-directories-first, "last" gives
reversed sorting.
Changes in sorting between elements of the same type (files,
directories) are not intended.
Differential Revision: https://reviews.freebsd.org/D48347
---
bin/ls/ls.1 | 19 ++++++++++++++++++-
bin/ls/ls.c | 35 +++++++++++++++++++++++++++++++----
bin/ls/util.c | 4 ++--
3 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 6aaa5025a6e1..b634f2f23ae6 100644
--- a/bin/ls/ls.1
+++ b/bin/ls/ls.1
@@ -39,6 +39,8 @@
.Nm
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1\&,
.Op Fl -color Ns = Ns Ar when
+.Op Fl -group-directories Ns = Ns Ar order
+.Op Fl -group-directories-first
.Op Fl D Ar format
.Op Ar
.Sh DESCRIPTION
@@ -303,6 +305,16 @@ options.
Display the long
.Pq Fl l
format output without the file owner's name or number.
+.It Fl -group-directories Ns = Ns Ar order
+Within results for each operand,
+group directories together and print them either
+.Cm first
+or
+.Cm last.
+.It Fl -group-directories-first
+Equivalent to
+.Fl -group-directories Ns = Ns Ar first .
+Implemented for compatibility with GNU coreutils.
.It Fl h
When used with the
.Fl l
@@ -914,8 +926,13 @@ and
.St -p1003.1-2008 .
The options
.Fl B , D , G , I , T , U , W , Z , b , h , v , w , y
-and
+,
.Fl ,
+.Fl -color
+and
+.Fl -group-directories Ns =
+(including
+.Fl -group-directories-first )
are non-standard extensions.
.Pp
The ACL support is compatible with
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index 048cfc9293e6..ca0fb9877b7e 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -87,12 +87,24 @@ static void display(const FTSENT *, FTSENT *, int);
static int mastercmp(const FTSENT * const *, const FTSENT * const *);
static void traverse(int, char **, int);
-#define COLOR_OPT (CHAR_MAX + 1)
+enum {
+ GRP_NONE = 0,
+ GRP_DIR_FIRST = -1,
+ GRP_DIR_LAST = 1
+};
+
+enum {
+ BIN_OPT = CHAR_MAX,
+ COLOR_OPT,
+ GROUP_OPT
+};
static const struct option long_opts[] =
{
- {"color", optional_argument, NULL, COLOR_OPT},
- {NULL, no_argument, NULL, 0}
+ {"color", optional_argument, NULL, COLOR_OPT},
+ {"group-directories", optional_argument, NULL, GROUP_OPT},
+ {"group-directories-first", no_argument, NULL, GROUP_OPT},
+ {NULL, no_argument, NULL, 0}
};
static void (*printfcn)(const DISPLAY *);
@@ -105,6 +117,7 @@ int termwidth = 80; /* default terminal width */
int f_accesstime; /* use time of last access */
int f_birthtime; /* use time of birth */
int f_flags; /* show flags associated with a file */
+static int f_groupdir = GRP_NONE;/* group directories first/last */
int f_humanval; /* show human-readable file sizes */
int f_inode; /* print inode */
static int f_kblocks; /* print size in kilobytes */
@@ -449,6 +462,15 @@ main(int argc, char *argv[])
case 'y':
f_samesort = 1;
break;
+ case GROUP_OPT:
+ if (optarg == NULL || strcmp(optarg, "first") == 0)
+ f_groupdir = GRP_DIR_FIRST;
+ else if (strcmp(optarg, "last") == 0)
+ f_groupdir = GRP_DIR_LAST;
+ else
+ errx(2, "unsupported --group-directories value '%s' (must be first or last)",
+ optarg);
+ break;
case COLOR_OPT:
#ifdef COLORLS
if (optarg == NULL || do_color_always(optarg))
@@ -1004,7 +1026,7 @@ label_out:
static int
mastercmp(const FTSENT * const *a, const FTSENT * const *b)
{
- int a_info, b_info;
+ int a_info, b_info, dir;
a_info = (*a)->fts_info;
if (a_info == FTS_ERR)
@@ -1023,5 +1045,10 @@ mastercmp(const FTSENT * const *a, const FTSENT * const *b)
if (b_info == FTS_D)
return (-1);
}
+
+ if (f_groupdir != GRP_NONE)
+ if ((dir = (a_info == FTS_D) - (b_info == FTS_D)) != 0)
+ return (f_groupdir * dir);
+
return (sortfcn(*a, *b));
}
diff --git a/bin/ls/util.c b/bin/ls/util.c
index 40610faa5fae..d83cae0e98d1 100644
--- a/bin/ls/util.c
+++ b/bin/ls/util.c
@@ -219,9 +219,9 @@ usage(void)
{
(void)fprintf(stderr,
#ifdef COLORLS
- "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [--color=when] [-D format]"
+ "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [--color=when] [-D format] [--group-directories=]"
#else
- "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [-D format]"
+ "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuvwxy1,] [-D format] [--group-directories=]"
#endif
" [file ...]\n");
exit(1);