bug-fileutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch for ls 4.1 -- Sort with directories first


From: Philip Flip Kromer
Subject: Patch for ls 4.1 -- Sort with directories first
Date: Mon, 22 Oct 2001 01:53:44 -0500 (CDT)

Hello, here is a creeping feature for ls. I prefer to see the directories
listed first, sorted separately from the files.  I added a new sort flag,
-Y or --sort=dirext, that sorts by extension, with directories 'smallest',
no extension next smallest, and sorted by filename within same extensions.
Thus any extension on a directory is ignored.  I am pretty sure this is
the right thing, as directories don't tend to have meaningful extensions,
and it makes hidden directories behave correctly.

I notice that QNX has this ability, but it uses the flag -v and is a
standalone option (with any sort, it puts the directories first).
http://qdn.qnx.com/support/docs/neutrino/utilities/l/ls.html

Please let me know if this is useful or should be improved upon.

flip

>>>>>>>>>>>>>>>>>>>>> Example: <<<<<<<<<<<<<<<<<<<<<<<<<

~$ ls -Xa    ###### OLD ######
bin/           .bash_logout          .ICEauthority    .rhosts
config/        .bash_profile         .kde/            .sawmill/
Desktop/       .bashrc               .kderc           .screenrc
friction/      .dir_colors           dead.letter      .ssh/
mail/          .emacs                .addressbook.lu  .wallpaper/
nsmail/        .enlightenment/       .Mathematica/    .Xauthority
pub/           .fullcircle/          .mc/             .Xdefaults
wallpaper@     .gnome/               .mozilla/        .xinitrc
zips/          .gnome-desktop/       .netscape/       .Xkeymaprc
./             .gnome-help-browser/  .pinerc          .xsession
../            .gnome_private/       .plan
.addressbook   .gtkrc                .profile
.bash_history  .history              .promptrc

~$ ls -Ya    ###### NEW ######
./                    mail/          .bash_history    .plan
../                   .Mathematica/  .bash_logout     .profile
bin/                  .mc/           .bash_profile    .promptrc
config/               .mozilla/      .bashrc          .rhosts
Desktop/              .netscape/     .dir_colors      .screenrc
.enlightenment/       nsmail/        .emacs           .Xauthority
friction/             pub/           .gtkrc           .Xdefaults
.fullcircle/          .sawmill/      .history         .xinitrc
.gnome/               .ssh/          .ICEauthority    .Xkeymaprc
.gnome-desktop/       .wallpaper/    .kderc           .xsession
.gnome-help-browser/  zips/          dead.letter
.gnome_private/       wallpaper@     .addressbook.lu
.kde/                 .addressbook   .pinerc


>>>>>>>>>>>>>>>>>>>>>>> Begin Patch <<<<<<<<<<<<<<<<<<<<<<<<<<

--- ls.old.c    Sun Apr 29 04:42:47 2001
+++ ls.c        Fri Oct 19 16:18:17 2001
@@ -293,6 +293,10 @@
                                      const struct fileinfo *file2));
 static int rev_cmp_extension PARAMS ((const struct fileinfo *file2,
                                      const struct fileinfo *file1));
+static int compare_dirext PARAMS ((const struct fileinfo *file1,
+                                     const struct fileinfo *file2));
+static int rev_cmp_dirext PARAMS ((const struct fileinfo *file2,
+                                     const struct fileinfo *file1));
 static int compare_version PARAMS ((const struct fileinfo *file1,
                                    const struct fileinfo *file2));
 static int rev_cmp_version PARAMS ((const struct fileinfo *file2,
@@ -429,6 +433,7 @@
     sort_none,                 /* -U */
     sort_name,                 /* default */
     sort_extension,            /* -X */
+    sort_dirext,               /* -Y */
     sort_time,                 /* -t */
     sort_size,                 /* -S */
     sort_version               /* -v */
@@ -720,12 +725,12 @@
 
 static char const *const sort_args[] =
 {
-  "none", "time", "size", "extension", "version", 0
+  "none", "time", "size", "extension", "dirext", "version", 0
 };
 
 static enum sort_type const sort_types[] =
 {
-  sort_none, sort_time, sort_size, sort_extension, sort_version
+  sort_none, sort_time, sort_size, sort_extension, sort_dirext, sort_version
 };
 
 static char const *const time_args[] =
@@ -1076,7 +1081,7 @@
     }
 
   while ((c = getopt_long (argc, argv,
-                          "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
+                          "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXY1",
                           long_options, NULL)) != -1)
     {
       switch (c)
@@ -1268,6 +1273,11 @@
          sort_type_specified = 1;
          break;
 
+       case 'Y':
+         sort_type = sort_dirext;
+         sort_type_specified = 1;
+         break;
+
        case '1':
          /* -1 has no effect after -l.  */
          if (format != long_format)
@@ -2163,6 +2173,9 @@
     case sort_extension:
       func = sort_reverse ? rev_cmp_extension : compare_extension;
       break;
+    case sort_dirext:
+      func = sort_reverse ? rev_cmp_dirext : compare_dirext;
+      break;
     case sort_size:
       func = sort_reverse ? rev_cmp_size : compare_size;
       break;
@@ -2317,6 +2330,51 @@
   return cmp;
 }
 
+/* Compare file extensions.  Directories are always 'smallest',
+   and are sorted by filename (ignoring extension, if any).
+   Files with no extension are next smallest.
+   If extensions are the same, compare by filenames instead. */
+
+static int
+compare_dirext (const struct fileinfo *file1, const struct fileinfo *file2)
+{
+  register char *base1, *base2;
+  register int cmp;
+
+  /* If both are directories, compare filename (ignore ext) */
+  if ( (file1->filetype == directory) && (file2->filetype == directory) )
+    return strcoll (file1->name, file2->name);
+
+  /* If one is a directory, it is smaller. */
+  if ( (file1->filetype == directory) && (file2->filetype != directory) )
+    return -1;
+  if ( (file1->filetype != directory) && (file2->filetype == directory) )
+    return 1;
+
+  /* Neither is a dir, use compare_extension */
+  return compare_extension(file1, file2);
+}
+
+static int
+rev_cmp_dirext (const struct fileinfo *file2, const struct fileinfo *file1)
+{
+  register char *base1, *base2;
+  register int cmp;
+
+  /* If both are directories, compare filename (ignore ext) */
+  if ( (file1->filetype == directory) && (file2->filetype == directory) )
+    return strcoll (file1->name, file2->name);
+
+  /* If one is a directory, it is smaller. */
+  if ( (file1->filetype == directory) && (file2->filetype != directory) )
+    return -1;
+  if ( (file1->filetype != directory) && (file2->filetype == directory) )
+    return 1;
+
+  /* Neither is a dir, use compare_extension */
+  return compare_extension(file1, file2);
+}
+
 /* List all the files now in the table.  */
 
 static void
@@ -3306,8 +3364,8 @@
 
       printf (_("\
   -S                         sort by file size\n\
-      --sort=WORD            extension -X, none -U, size -S, time -t,\n\
-                               version -v\n\
+      --sort=WORD            extension -X, dirext -Y, none -U, size -S,\n\
+                               time -t, version -v\n\
                              status -c, time -t, atime -u, access -u, use -u\n\
       --time=WORD            show time as WORD instead of modification time:\n\
                                atime, access, use, ctime or status; use\n\
@@ -3322,6 +3380,8 @@
   -w, --width=COLS           assume screen width instead of current value\n\
   -x                         list entries by lines instead of by columns\n\
   -X                         sort alphabetically by entry extension\n\
+  -Y                         sort alphabetically by entry extension, but\n\
+                             place directories first in the listing\n\
   -1                         list one file per line\n\
       --help                 display this help and exit\n\
       --version              output version information and exit\n\




reply via email to

[Prev in Thread] Current Thread [Next in Thread]