Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Nov 2012 00:24:26 +0000 (UTC)
From:      Greg Lehey <grog@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r242725 - head/bin/ls
Message-ID:  <201211080024.qA80OQU2038483@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grog
Date: Thu Nov  8 00:24:26 2012
New Revision: 242725
URL: http://svnweb.freebsd.org/changeset/base/242725

Log:
  Add y flag and environment variable LS_SAMESORT to specify the same
  sorting order for time and name with the -t option.  IEEE Std 1003.2
  (POSIX.2) mandates that the -t option sort in descending order, and
  that if two files have the same timestamp, they should be sorted in
  ascending order of their names.  The -r flag reverses both of these
  sort orders, so they're never the same.  This creates significant
  problems for sequentially named files stored on FAT file systems,
  where it can be impossible to list them in the order in which they
  were created.
  
  Add , (comma) option to print file sizes grouped and separated by
  thousands using the non-monetary separator returned by localeconv(3),
  typically a comma or period.
  
  MFC after:  14 days

Modified:
  head/bin/ls/cmp.c
  head/bin/ls/ls.1
  head/bin/ls/ls.c
  head/bin/ls/ls.h
  head/bin/ls/print.c
  head/bin/ls/util.c

Modified: head/bin/ls/cmp.c
==============================================================================
--- head/bin/ls/cmp.c	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/cmp.c	Thu Nov  8 00:24:26 2012	(r242725)
@@ -78,7 +78,10 @@ modcmp(const FTSENT *a, const FTSENT *b)
 	if (b->fts_statp->st_mtim.tv_nsec <
 	    a->fts_statp->st_mtim.tv_nsec)
 		return (-1);
-	return (strcoll(a->fts_name, b->fts_name));
+        if (f_samesort)
+		return (strcoll(b->fts_name, a->fts_name));
+        else
+		return (strcoll(a->fts_name, b->fts_name));
 }
 
 int
@@ -104,7 +107,10 @@ acccmp(const FTSENT *a, const FTSENT *b)
 	if (b->fts_statp->st_atim.tv_nsec <
 	    a->fts_statp->st_atim.tv_nsec)
 		return (-1);
-	return (strcoll(a->fts_name, b->fts_name));
+        if (f_samesort)
+		return (strcoll(b->fts_name, a->fts_name));
+        else
+		return (strcoll(a->fts_name, b->fts_name));
 }
 
 int
@@ -130,7 +136,10 @@ birthcmp(const FTSENT *a, const FTSENT *
 	if (b->fts_statp->st_birthtim.tv_nsec <
 	    a->fts_statp->st_birthtim.tv_nsec)
 		return (-1);
-	return (strcoll(a->fts_name, b->fts_name));
+        if (f_samesort)
+		return (strcoll(b->fts_name, a->fts_name));
+        else
+		return (strcoll(a->fts_name, b->fts_name));
 }
 
 int
@@ -156,7 +165,10 @@ statcmp(const FTSENT *a, const FTSENT *b
 	if (b->fts_statp->st_ctim.tv_nsec <
 	    a->fts_statp->st_ctim.tv_nsec)
 		return (-1);
-	return (strcoll(a->fts_name, b->fts_name));
+        if (f_samesort)
+		return (strcoll(b->fts_name, a->fts_name));
+        else
+		return (strcoll(a->fts_name, b->fts_name));
 }
 
 int

Modified: head/bin/ls/ls.1
==============================================================================
--- head/bin/ls/ls.1	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/ls.1	Thu Nov  8 00:24:26 2012	(r242725)
@@ -32,7 +32,7 @@
 .\"     @(#)ls.1	8.7 (Berkeley) 7/29/94
 .\" $FreeBSD$
 .\"
-.Dd September 28, 2011
+.Dd November 8, 2012
 .Dt LS 1
 .Os
 .Sh NAME
@@ -40,7 +40,7 @@
 .Nd list directory contents
 .Sh SYNOPSIS
 .Nm
-.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1
+.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,
 .Op Fl D Ar format
 .Op Ar
 .Sh DESCRIPTION
@@ -130,6 +130,8 @@ This option is equivalent to defining
 .Ev CLICOLOR
 in the environment.
 (See below.)
+This functionality can be compiled out by removing the definition of
+.Ev COLORLS .
 .It Fl H
 Symbolic links on the command line are followed.
 This option is assumed if
@@ -249,12 +251,35 @@ subsection below, except (if the long fo
 the directory totals are not output when the output is in a
 single column, even if multi-column output is requested.
 .It Fl t
-Sort by time modified (most recently modified
-first) before sorting the operands in lexicographical
-order.
+Sort by descending time modified (most recently modified first).  If two files
+have the same modification timestamp, sort their names in ascending
+lexicographical order.
+The
+.Fl r
+option reverses both of these sort orders.
+.Pp
+Note that these sort orders are contradictory: the time sequence is in
+descending order, the lexicographical sort is in ascending order.
+This behavior is mandated by
+.St -p1003.2 .
+This feature can cause problems listing files stored with sequential names on
+FAT file systems, such as from digital cameras, where it is possible to have
+more than one image with the same timestamp.
+In such a case, the photos cannot be listed in the sequence in which
+they were taken.
+To ensure the same sort order for time and for lexicographical sorting, set the
+environment variable
+.Ev LS_SAMESORT
+or use the
+.Fl y
+option.
+This causes
+.Nm
+to reverse the lexicographal sort order when sorting files with the
+same modification timestamp.
 .It Fl u
 Use time of last access,
-instead of last modification
+instead of time of last modification
 of the file for sorting
 .Pq Fl t
 or printing
@@ -268,6 +293,15 @@ The same as
 .Fl C ,
 except that the multi-column output is produced with entries sorted
 across, rather than down, the columns.
+.It Fl y
+When the
+.Fl t
+option is set, sort the alphabetical output in the same order as the time output.
+This has the same effect as setting
+.Ev LS_SAMESORT .
+See the description of the
+.Fl t
+option for more details.
 .It Fl 1
 (The numeric digit
 .Dq one . )
@@ -275,6 +309,15 @@ Force output to be
 one entry per line.
 This is the default when
 output is not to a terminal.
+.It Fl ,
+(Comma) When the
+.Fl l
+option is set, print file sizes grouped and separated by thousands using the
+non-monetary separator returned by
+.Xr localeconv 3 ,
+typically a comma or period.
+If no locale is set, or the locale does not have a non-monetary separator, this
+option has no effect.
 .El
 .Pp
 The
@@ -529,7 +572,7 @@ variable is defined.
 .It Ev CLICOLOR_FORCE
 Color sequences are normally disabled if the output is not directed to
 a terminal.
-This can be overridden by setting this flag.
+This can be overridden by setting this variable.
 The
 .Ev TERM
 variable still needs to reference a color capable terminal however
@@ -655,6 +698,14 @@ Not all columns have changeable widths.
 The fields are,
 in order: inode, block count, number of links, user name,
 group name, flags, file size, file name.
+.It Ev LS_SAMESORT
+If this variable is set, the
+.Fl t
+option sorts the names of files with the same modification timestamp in the same
+sense as the time sort.
+See the description of the
+.Fl t
+option for more details.
 .It Ev TERM
 The
 .Ev CLICOLOR
@@ -678,6 +729,7 @@ specification.
 .Xr getfacl 1 ,
 .Xr sort 1 ,
 .Xr xterm 1 ,
+.Xr localeconv 3 ,
 .Xr strftime 3 ,
 .Xr strmode 3 ,
 .Xr termcap 5 ,
@@ -716,3 +768,9 @@ option description might be a feature th
 based on the fact that single-column output
 usually goes to something other than a terminal.
 It is debatable whether this is a design bug.
+.Pp
+.St -p1003.2
+mandates opposite sort orders for files with the same timestamp when
+sorting with the
+.Fl t
+option.

Modified: head/bin/ls/ls.c
==============================================================================
--- head/bin/ls/ls.c	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/ls.c	Thu Nov  8 00:24:26 2012	(r242725)
@@ -109,10 +109,11 @@ int termwidth = 80;		/* default terminal
        int f_humanval;		/* show human-readable file sizes */
        int f_inode;		/* print inode */
 static int f_kblocks;		/* print size in kilobytes */
+       int f_label;		/* show MAC label */
 static int f_listdir;		/* list actual directory, not contents */
 static int f_listdot;		/* list files beginning with . */
-static int f_noautodot;		/* do not automatically enable -A for root */
        int f_longform;		/* long listing format */
+static int f_noautodot;		/* do not automatically enable -A for root */
 static int f_nofollow;		/* don't follow symbolic link arguments */
        int f_nonprint;		/* show unprintables as ? */
 static int f_nosort;		/* don't sort output */
@@ -122,19 +123,21 @@ static int f_numericonly;	/* don't conve
        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 */
-       int f_sectime;		/* print the real time for all files */
+       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 */
        int f_size;		/* list size in short listing */
+static int f_sizesort;
        int f_slash;		/* similar to f_type, but only for dirs */
        int f_sortacross;	/* sort across rows, not down columns */
        int f_statustime;	/* use time of last mode change */
 static int f_stream;		/* stream the output, separate with commas */
-static int f_timesort;		/* sort by time vice name */
+       int f_thousands;		/* show file sizes with thousands separators */
        char *f_timeformat;      /* user-specified time format */
-static int f_sizesort;
+static int f_timesort;		/* sort by time vice name */
        int f_type;		/* add type character for non-regular files */
 static int f_whiteout;		/* show whiteout entries */
-       int f_label;		/* show MAC label */
+
 #ifdef COLORLS
        int f_color;		/* add type in color for non-regular files */
 
@@ -180,8 +183,10 @@ main(int argc, char *argv[])
 	}
 
 	fts_options = FTS_PHYSICAL;
+	if (getenv("LS_SAMESORT"))
+		f_samesort = 1;
  	while ((ch = getopt(argc, argv,
-	    "1ABCD:FGHILPRSTUWZabcdfghiklmnopqrstuwx")) != -1) {
+	    "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) {
 		switch (ch) {
 		/*
 		 * The -1, -C, -x and -l options all override each other so
@@ -237,6 +242,9 @@ main(int argc, char *argv[])
 			f_sizesort = 0;
 			break;
                 /* Other flags.  Please keep alphabetic. */
+		case ',':
+			f_thousands = 1;
+			break;
 		case 'B':
 			f_nonprint = 0;
 			f_octal = 1;
@@ -338,6 +346,9 @@ main(int argc, char *argv[])
 			f_octal = 0;
 			f_octal_escape = 0;
 			break;
+		case 'y':
+			f_samesort = 1;
+			break;
 		default:
 		case '?':
 			usage();
@@ -850,6 +861,8 @@ label_out:
 			d.s_size = sizelen;
 		d.s_user = maxuser;
 	}
+        if (f_thousands)                        /* make space for commas */
+		d.s_size += (d.s_size - 1) / 3;
 	printfcn(&d);
 	output = 1;
 

Modified: head/bin/ls/ls.h
==============================================================================
--- head/bin/ls/ls.h	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/ls.h	Thu Nov  8 00:24:26 2012	(r242725)
@@ -49,11 +49,13 @@ extern int f_longform;		/* long listing 
 extern int f_octal;		/* print unprintables in octal */
 extern int f_octal_escape;	/* like f_octal but use C escapes if possible */
 extern int f_nonprint;		/* show unprintables as ? */
+extern int f_samesort;          /* sort time and name in same direction */
 extern int f_sectime;		/* print the real time for all files */
 extern int f_size;		/* list size in short listing */
 extern int f_slash;		/* append a '/' if the file is a directory */
 extern int f_sortacross;	/* sort across rows, not down columns */
 extern int f_statustime;	/* use time of last mode change */
+extern int f_thousands;		/* show file sizes with thousands separators */
 extern char *f_timeformat;      /* user-specified time format */
 extern int f_notabs;		/* don't use tab-separated multi-col output */
 extern int f_type;		/* add type character for non-regular files */

Modified: head/bin/ls/print.c
==============================================================================
--- head/bin/ls/print.c	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/print.c	Thu Nov  8 00:24:26 2012	(r242725)
@@ -606,7 +606,11 @@ printsize(size_t width, off_t bytes)
 		humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
 		    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
 		(void)printf("%*s ", (u_int)width, buf);
-	} else
+	} else if (f_thousands) {               /* with commas */
+		/* This format assignment needed to work round gcc bug. */
+                const char *format = "%*j'd ";
+		(void)printf(format, (u_int)width, bytes);
+        } else
 		(void)printf("%*jd ", (u_int)width, bytes);
 }
 

Modified: head/bin/ls/util.c
==============================================================================
--- head/bin/ls/util.c	Wed Nov  7 23:50:28 2012	(r242724)
+++ head/bin/ls/util.c	Thu Nov  8 00:24:26 2012	(r242725)
@@ -175,7 +175,7 @@ prn_octal(const char *s)
 	size_t clen;
 	unsigned char ch;
 	int goodchar, i, len, prtlen;
-	
+
 	memset(&mbs, 0, sizeof(mbs));
 	len = 0;
 	while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
@@ -222,9 +222,9 @@ usage(void)
 {
 	(void)fprintf(stderr,
 #ifdef COLORLS
-	"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
+	"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
 #else
-	"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
+	"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
 #endif
 		      " [file ...]\n");
 	exit(1);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211080024.qA80OQU2038483>