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);