bin/116425: [patch]ls options for pre-sort of directories first or
last, & listing of directories or non-directories explicitly
Victor Vaile
bsdls at vaile.info
Mon Sep 17 15:10:02 PDT 2007
>Number: 116425
>Category: bin
>Synopsis: [patch]ls options for pre-sort of directories first or last, & listing of directories or non-directories explicitly
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Sep 17 22:10:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Victor Vaile
>Release: 6.2-STABLE-200708
>Organization:
>Environment:
FreeBSD engineering08.efilm.com 6.2-STABLE-200708 FreeBSD 6.2-STABLE-200708 #0: Tue Sep 11 12:26:16 UTC 2007 Rvev at engineering08.vaile.info:/usr/obj/usr/src/sys/ENGINEERINGSMP i386
>Description:
I seem to recall seeing a PR asking about one of these options quite some time ago, however I didn't see any response posted back then, and my search today did not yeild any results. (If this is a duplicate request, my apologies are hereby included.)
The previous request had asked for a way to cause ls to return directories first or last in the listing, with the various sorting options applied to the directory, and non-directory groups individually. In addition, I was looking for a way to get ls to output only directories, or only non-directories. I don't recall when I started to use this initally, but I updated the patch that I used when I upgraded a machine to 6.2-RELEASE. I've just installed a machine with 6.2-STABLE-200708 last week, and used the same updated patch today which still seems to work fine.
This is non-critical of course, and although I've not had the inclusion of the options added effect anything adversly on any of the systems I've installed it, I suspect there might be some discussion needed as to whether such options should be included in the regular distribution. I have found the options to be quite handy.
As there aren't many free single character command line options left, my choices of options (D,V,N for sorting directories first,last,no sort[normal], and v,z,e for listing only directories, only non-directories, everything [normal]) may not be all that intuitive, and could be changed if desired.
>How-To-Repeat:
>Fix:
I've included a patch that adds the features mentioned above to ls that works as of 6.2-STABLE-200708. This also updates the manpage with the options added.
Patch attached with submission follows:
diff -u ls/cmp.c ls.new/cmp.c
--- ls/cmp.c Thu May 18 15:02:20 2006
+++ ls.new/cmp.c Thu May 17 04:14:52 2007
@@ -183,3 +183,35 @@
return (sizecmp(b, a));
}
+
+#define IS_FTS_DIR(x) ((x)->fts_info == FTS_D \
+ || (x)->fts_info == FTS_DOT \
+ || (x)->fts_info == FTS_DC \
+ || (x)->fts_info == FTS_DNR \
+ || (x)->fts_info == FTS_DP)
+
+int
+dirfcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if ((IS_FTS_DIR(a) && IS_FTS_DIR(b)) || (!IS_FTS_DIR(a) && !IS_FTS_DIR(b)))
+ return (real_sortfcn(a, b));
+ return (IS_FTS_DIR(a) ? -1 : 1);
+}
+
+int
+revdirfcmp(const FTSENT *a, const FTSENT *b)
+{
+
+ if ((IS_FTS_DIR(a) && IS_FTS_DIR(b)) || (!IS_FTS_DIR(a) && !IS_FTS_DIR(b)))
+ return (real_sortfcn(a, b));
+ return (IS_FTS_DIR(b) ? -1 : 1);
+}
+int
+checkisdir(const FTSENT *a)
+{
+ if (IS_FTS_DIR(a))
+ return (0);
+ else
+ return (1);
+}
diff -u ls/extern.h ls.new/extern.h
--- ls/extern.h Thu May 18 15:02:20 2006
+++ ls.new/extern.h Thu May 17 04:14:52 2007
@@ -42,6 +42,12 @@
int revstatcmp(const FTSENT *, const FTSENT *);
int sizecmp(const FTSENT *, const FTSENT *);
int revsizecmp(const FTSENT *, const FTSENT *);
+int dirfcmp(const FTSENT *, const FTSENT *);
+int revdirfcmp(const FTSENT *, const FTSENT *);
+int checkisdir(const FTSENT *);
+
+/* save the real sortfcn when sorting directories first */
+int (*real_sortfcn)(const FTSENT *, const FTSENT *);
void printcol(const DISPLAY *);
void printlong(const DISPLAY *);
diff -u ls/ls.1 ls.new/ls.1
--- ls/ls.1 Mon Oct 16 04:54:36 2006
+++ ls.new/ls.1 Fri May 18 02:05:57 2007
@@ -40,7 +40,7 @@
.Nd list directory contents
.Sh SYNOPSIS
.Nm
-.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1
+.Op Fl ABCDFGHILNPRSTUVWZabcdefghiklmnopqrstuvwxz1
.Op Ar
.Sh DESCRIPTION
For each operand that names a
@@ -88,6 +88,10 @@
is the numeric value of the character in octal.
.It Fl C
Force multi-column output; this is the default when output is to a terminal.
+.It Fl D
+Sorts directories first. This is independent of the
+.Fl r
+option.
.It Fl F
Display a slash
.Pq Ql /
@@ -132,6 +136,12 @@
This option cancels the
.Fl P
option.
+.It Fl N
+Negates sorting directories first or last (the
+.Fl D
+and
+.Fl V
+options).
.It Fl P
If argument is a symbolic link, list the link itself rather than the
object the link references.
@@ -154,6 +164,10 @@
month, day, hour, minute, second, and year.
.It Fl U
Use time when file was created for sorting or printing.
+.It Fl V
+Sorts directories last. This is independent of the
+.Fl r
+option.
.It Fl W
Display whiteouts when scanning directories.
.It Fl Z
@@ -173,6 +187,12 @@
Use time when file status was last changed for sorting or printing.
.It Fl d
Directories are listed as plain files (not searched recursively).
+.It Fl e
+List everything (not strictly, but negates the
+.Fl v
+and
+.Fl z
+options).
.It Fl f
Output is not sorted.
.It Fl g
@@ -242,6 +262,8 @@
.Pq Fl t
or printing
.Pq Fl l .
+.It Fl v
+Lists only directories.
.It Fl w
Force raw printing of non-printable characters.
This is the default
@@ -251,6 +273,8 @@
.Fl C ,
except that the multi-column output is produced with entries sorted
across, rather than down, the columns.
+.It Fl z
+Lists only non-directories.
.It Fl 1
(The numeric digit
.Dq one . )
diff -u ls/ls.c ls.new/ls.c
--- ls/ls.c Thu May 18 15:02:20 2006
+++ ls.new/ls.c Thu May 17 04:21:40 2007
@@ -105,6 +105,10 @@
/* flags */
int f_accesstime; /* use time of last access */
int f_birthtime; /* use time of birth */
+static int f_dirfirstsort; /* put directories first */
+static int f_dirlastsort; /* put directories last */
+static int f_dirlistonly; /* list directories only */
+static int f_dirlistnone; /* list non-directories only */
int f_flags; /* show flags associated with a file */
int f_humanval; /* show human-readable file sizes */
int f_inode; /* print inode */
@@ -179,11 +183,12 @@
fts_options = FTS_PHYSICAL;
while ((ch = getopt(argc, argv,
- "1ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx")) != -1) {
+ "1ABCDFGHILNPRSTUVWZabcdefghiklmnopqrstuvwxz")) != -1) {
switch (ch) {
/*
- * The -1, -C, -x and -l options all override each other so
- * shell aliasing works right.
+ * The -1, -C, -x and -l options all override each other,
+ * as do also the -D and -Z options, and the -v and -z
+ * options so shell aliasing works right.
*/
case '1':
f_singlecol = 1;
@@ -198,6 +203,30 @@
case 'C':
f_sortacross = f_longform = f_singlecol = 0;
break;
+ case 'D':
+ f_dirfirstsort = 1;
+ f_dirlastsort = 0;
+ break;
+ case 'V':
+ f_dirfirstsort = 0;
+ f_dirlastsort = 1;
+ break;
+ case 'N':
+ f_dirfirstsort = 0;
+ f_dirlastsort = 0;
+ break;
+ case 'v':
+ f_dirlistonly = 1;
+ f_dirlistnone = 0;
+ break;
+ case 'z':
+ f_dirlistonly = 0;
+ f_dirlistnone = 1;
+ break;
+ case 'e':
+ f_dirlistonly = 0;
+ f_dirlistnone = 0;
+ break;
case 'l':
f_longform = 1;
f_singlecol = 0;
@@ -376,12 +405,13 @@
#endif
/*
- * If not -F, -i, -l, -s, -S or -t options, don't require stat
- * information, unless in color mode in which case we do
- * need this to determine which colors to display.
+ * If not -D, -V, -v, -z, -F, -i, -l, -s, -S or -t options, don't
+ * require stat information, unless in color mode in which case
+ * we do need this to determine which colors to display.
*/
if (!f_inode && !f_longform && !f_size && !f_timesort &&
- !f_sizesort && !f_type
+ !f_sizesort && !f_type && !f_dirfirstsort && !f_dirlastsort &&
+ !f_dirlistonly && !f_dirlistnone
#ifdef COLORLS
&& !f_color
#endif
@@ -426,6 +456,14 @@
sortfcn = revsizecmp;
else /* Use modification time. */
sortfcn = revmodcmp;
+ if (f_dirfirstsort) {
+ real_sortfcn = sortfcn;
+ sortfcn = dirfcmp;
+ } else if (f_dirlastsort) {
+ real_sortfcn = sortfcn;
+ sortfcn = revdirfcmp;
+ }
+
} else {
if (!f_timesort && !f_sizesort)
sortfcn = namecmp;
@@ -439,6 +477,14 @@
sortfcn = sizecmp;
else /* Use modification time. */
sortfcn = modcmp;
+ if (f_dirfirstsort) {
+ real_sortfcn = sortfcn;
+ sortfcn = dirfcmp;
+ } else if (f_dirlastsort) {
+ real_sortfcn = sortfcn;
+ sortfcn = revdirfcmp;
+ }
+
}
/* Select a print function. */
@@ -653,6 +699,20 @@
cur->fts_number = NO_PRINT;
rval = 1;
continue;
+ }
+ /*
+ * Tell to print (only dirs|no dirs) if set
+ */
+ if (f_dirlistonly) {
+ if (checkisdir(cur)) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
+ } else if (f_dirlistnone) {
+ if (! checkisdir(cur)) {
+ cur->fts_number = NO_PRINT;
+ continue;
+ }
}
/*
* P is NULL if list is the argv list, to which different rules
diff -u ls/util.c ls.new/util.c
--- ls/util.c Thu May 18 15:02:20 2006
+++ ls.new/util.c Thu May 17 04:23:21 2007
@@ -222,9 +222,9 @@
{
(void)fprintf(stderr,
#ifdef COLORLS
- "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1]"
+ "usage: ls [-ABCDFGHILNPRSTUVWZabcdefghiklmnopqrstuvwxz1]"
#else
- "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwx1]"
+ "usage: ls [-ABCDFHILNPRSTUVWZabcdefghiklmnopqrstuvwxz1]"
#endif
" [file ...]\n");
exit(1);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list