ls(1): Fix sort-by-size bug
authorJohn Marino <draco@marino.st>
Tue, 8 Dec 2015 22:41:22 +0000 (23:41 +0100)
committerJohn Marino <draco@marino.st>
Tue, 8 Dec 2015 22:46:19 +0000 (23:46 +0100)
For a reason that escapes me, in order to sort files by size using ls(1),
one had to pass both the size sort switch (-S) and the time sort switch
(-t), otherwise the -S flag would be ignored.  This hacky workaround was
documented in the man page as well.

Let's fix this with code taken from FreeBSD.  The -t and -S switches are
now mutually exclusive.  If someone uses them together, then the last
one wins (e.g. ls -st sorts by mod. time and -ts sorts by file size)

bin/ls/ls.1
bin/ls/ls.c

index c635641..153056e 100644 (file)
@@ -31,7 +31,7 @@
 .\"     @(#)ls.1       8.7 (Berkeley) 7/29/94
 .\" $FreeBSD: src/bin/ls/ls.1,v 1.86 2005/02/13 22:25:09 ru Exp $
 .\"
-.Dd November 20, 2015
+.Dd December 8, 2015
 .Dt LS 1
 .Os
 .Sh NAME
@@ -142,8 +142,8 @@ options.
 .It Fl R
 Recursively list subdirectories encountered.
 .It Fl S
-Use the size of a file for sorting
-.Pq Fl t .
+Sort by size (largest file first) before sorting the operands in
+lexicographical order.
 .It Fl T
 When used with the
 .Fl l
@@ -290,6 +290,13 @@ options override each other; the last one specified determines
 the file time used.
 .Pp
 The
+.Fl S
+and
+.Fl t
+options override each other; the last one specified determines
+the sort order used.
+.Pp
+The
 .Fl B , b , w ,
 and
 .Fl q
index 604d4ad..1472445 100644 (file)
@@ -113,7 +113,7 @@ static int f_reversesort;   /* reverse whatever sort is used */
 static int f_singlecol;                /* use single column output */
        int f_size;             /* list size in short listing */
        int f_slash;            /* similar to f_type, but only for dirs */
-       int f_sortsize;         /* Sort by size */
+       int f_sizesort;         /* Sort by size */
        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 */
@@ -241,8 +241,14 @@ main(int argc, char *argv[])
                case 'R':
                        f_recursive = 1;
                        break;
+               /* The -t and -S options override each other. */
                case 'S':
-                       f_sortsize = 1;
+                       f_sizesort = 1;
+                       f_timesort = 0;
+                       break;
+               case 't':
+                       f_timesort = 1;
+                       f_sizesort = 0;
                        break;
                case 'f':
                        f_nosort = 1;
@@ -299,9 +305,6 @@ main(int argc, char *argv[])
                case 'T':
                        f_sectime = 1;
                        break;
-               case 't':
-                       f_timesort = 1;
-                       break;
                case 'W':
                        f_whiteout = 1;
                        break;
@@ -361,12 +364,12 @@ main(int argc, char *argv[])
 #endif
 
        /*
-        * If not -F, -i, -l, -s, -S  or -t options, don't require stat
+        * 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 (!f_inode && !f_longform && !f_size && !f_sortsize && !f_timesort
-           && !f_type
+       if (!f_inode && !f_longform && !f_size && !f_timesort &&
+           !f_sizesort && !f_type
 #ifdef COLORLS
            && !f_color
 #endif
@@ -399,23 +402,23 @@ main(int argc, char *argv[])
        }
        /* Select a sort function. */
        if (f_reversesort) {
-               if (!f_timesort)
+               if (!f_timesort && !f_sizesort)
                        sortfcn = revnamecmp;
+               else if (f_sizesort)
+                       sortfcn = revsizecmp;
                else if (f_accesstime)
                        sortfcn = revacccmp;
-               else if (f_sortsize)
-                       sortfcn = revsizecmp;
                else if (f_statustime)
                        sortfcn = revstatcmp;
                else            /* Use modification time. */
                        sortfcn = revmodcmp;
        } else {
-               if (!f_timesort)
+               if (!f_timesort && !f_sizesort)
                        sortfcn = namecmp;
+               else if (f_sizesort)
+                       sortfcn = sizecmp;
                else if (f_accesstime)
                        sortfcn = acccmp;
-               else if (f_sortsize)
-                       sortfcn = sizecmp;
                else if (f_statustime)
                        sortfcn = statcmp;
                else            /* Use modification time. */