Attached is a patch which adds support for a directory-first sort mode 
for ls. This mode can be used in two ways:

-e/--dirsfirst [--sort=method]: Sorts directories first, then by the 
specified method (by name, by default)
--sort=dirsfirst: Sorts directories first, then by name
diff -Naur fileutils-4.1.11/src/ls.c fileutils-4.1.11-dirsfirst/src/ls.c
--- fileutils-4.1.11/src/ls.c   2002-07-20 02:50:44.000000000 -0400
+++ fileutils-4.1.11-dirsfirst/src/ls.c 2003-06-25 14:30:26.000000000 -0400
@@ -439,7 +439,8 @@
     sort_extension,            /* -X */
     sort_time,                 /* -t */
     sort_size,                 /* -S */
-    sort_version               /* -v */
+    sort_version,              /* -v */
+    sort_dirsfirst              /* -e */
   };
 
 static enum sort_type sort_type;
@@ -484,6 +485,12 @@
    strange characters in file names.  */
 static int dired;
 
+/* Put directories first */
+static int dirsfirst = 0;
+
+/* Real sorting func */
+int (*real_sort_func) PARAMS ((void *, void *)) = NULL;
+
 /* `none' means don't mention the type of files.
    `classify' means mention file types and mark executables.
    `file_type' means mention only file types.
@@ -716,6 +723,7 @@
   {"escape", no_argument, 0, 'b'},
   {"directory", no_argument, 0, 'd'},
   {"dired", no_argument, 0, 'D'},
+  {"dirsfirst", no_argument, 0, 'e'},
   {"full-time", no_argument, 0, FULL_TIME_OPTION},
   {"human-readable", no_argument, 0, 'h'},
   {"inode", no_argument, 0, 'i'},
@@ -767,12 +775,12 @@
 
 static char const *const sort_args[] =
 {
-  "none", "time", "size", "extension", "version", 0
+  "none", "time", "size", "extension", "version", "dirsfirst", 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_version, sort_dirsfirst
 };
 
 static char const *const time_args[] =
@@ -1053,7 +1061,7 @@
     }
 
   format_needs_stat = sort_type == sort_time || sort_type == sort_size
-    || format == long_format
+    || format == long_format || dirsfirst || sort_type == sort_dirsfirst
     || dereference == DEREF_ALWAYS
     || recursive || print_block_size || print_inode;
   format_needs_type = (format_needs_stat == 0
@@ -1295,7 +1303,7 @@
   }
 
   while ((c = getopt_long (argc, argv,
-                          "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
+                          "abcdefghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
                           long_options, NULL)) != -1)
     {
       switch (c)
@@ -1320,6 +1328,10 @@
          immediate_dirs = 1;
          break;
 
+       case 'e':
+         dirsfirst = 1;
+         break;
+
        case 'f':
          /* Same as enabling -a -U and disabling -l -s.  */
          all_files = 1;
@@ -1667,7 +1679,6 @@
              }
          }
     }
-
   return optind;
 }
 
@@ -2555,6 +2566,22 @@
 static int rev_cmp_extension (V a, V b) { return compare_extension (b, a); }
 static int rev_str_extension (V a, V b) { return compstr_extension (b, a); }
 
+static inline int cmp_dirsfirst (const struct fileinfo *a, const struct fileinfo *b)
+{
+  if(S_ISDIR(a->stat.st_mode) == S_ISDIR(b->stat.st_mode))
+    return real_sort_func(a, b);
+  return S_ISDIR(a->stat.st_mode) ? -1 : 1;
+}
+
+static inline int rev_cmp_dirsfirst (V a, V b)
+{
+  return cmp_dirsfirst(b, a);
+}
+
+static inline int compare_dirsfirst (V a, V b){
+  return cmp_dirsfirst(a, b);
+}
+
 /* Sort the files now in the table.  */
 
 static void
@@ -2562,6 +2589,10 @@
 {
   int (*func) PARAMS ((V, V));
 
+  if(sort_type == sort_dirsfirst){
+    dirsfirst = 1;
+    sort_type = sort_name;
+  }
   switch (sort_type)
     {
     case sort_none:
@@ -2637,6 +2668,11 @@
        }
     }
 
+  if(dirsfirst){
+    real_sort_func = func;
+    func = sort_reverse ? rev_cmp_dirsfirst : compare_dirsfirst;
+  }
+
   qsort (files, files_index, sizeof (struct fileinfo), func);
 }
 
@@ -3630,6 +3666,7 @@
   -D, --dired                generate output designed for Emacs' dired mode\n\
 "), stdout);
       fputs (_("\
+  -e, --dirsfirst            put directories first\n\
   -f                         do not sort, enable -aU, disable -lst\n\
   -F, --classify             append indicator (one of */=@|) to entries\n\
       --format=WORD          across -x, commas -m, horizontal -x, long -l,\n\
@@ -3680,7 +3717,7 @@
       fputs (_("\
   -S                         sort by file size\n\
       --sort=WORD            extension -X, none -U, size -S, time -t,\n\
-                               version -v\n\
+                               version -v, dirsfirst -e\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\
_______________________________________________
Bug-coreutils mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-coreutils

Reply via email to