I introduced 2 new options to ls:

-e, --sort=dirsfirst
This sort option makes ls list directories first.

-j
This is used to range in noncapitals while sorting.
This way the listing is truely sorted alphabetically.

The attached diff is based on fileutils-4.1

Just unpack the fileutils-4.1.tar.gz, copy the file
fu-41.patch to fileutils-4.1/src. Change to the 
directory and call: 'patch < fu-41.patch'
Then follow the usual install instructions.


Florian.



--- ls.c	Sun Apr 29 11:42:47 2001
+++ ls.c.dirsfirstrangein	Sat Nov  3 20:36:29 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_dirsfirst PARAMS ((const struct fileinfo *file1,
+				 const struct fileinfo *file2));
+static int rev_cmp_dirsfirst 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,
@@ -422,7 +426,7 @@
 
 static int full_time;
 
-/* The file characteristic to sort by.  Controlled by -t, -S, -U, -X, -v. */
+/* The file characteristic to sort by.  Controlled by -t, -S, -U, -X, -v, -e. */
 
 enum sort_type
   {
@@ -431,7 +435,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;
@@ -720,12 +725,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[] =
@@ -771,6 +776,8 @@
    for the separating white space.  */
 #define MIN_COLUMN_WIDTH	3
 
+/* Default sorting function is strcoll(), considering the locale. */ 
+static int (*strcmpfunc)() = strcoll;
 
 /* This zero-based index is used solely with the --dired option.
    When that option is in effect, this counter is incremented for each
@@ -877,7 +884,7 @@
     }
 
   format_needs_stat = sort_type == sort_time || sort_type == sort_size
-    || format == long_format
+    || sort_type == sort_dirsfirst || format == long_format
     || trace_links || trace_dirs || print_block_size || print_inode;
   format_needs_type = (format_needs_stat == 0
 		       && (print_with_color || indicator_style != none));
@@ -1076,7 +1083,7 @@
     }
 
   while ((c = getopt_long (argc, argv,
-			   "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
+			   "abcdefghijklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
 			   long_options, NULL)) != -1)
     {
       switch (c)
@@ -1101,6 +1108,11 @@
 	  immediate_dirs = 1;
 	  break;
 
+	case 'e':
+	  sort_type = sort_dirsfirst;
+	  sort_type_specified = 1;
+	  break;
+
 	case 'f':
 	  /* Same as enabling -a -U and disabling -l -s.  */
 	  all_files = 1;
@@ -1136,6 +1148,10 @@
 	  print_inode = 1;
 	  break;
 
+	case 'j':
+	  strcmpfunc = strcasecmp;
+	  break;
+
 	case 'k':
 	  output_block_size = 1024;
 	  break;
@@ -2169,6 +2185,9 @@
     case sort_version:
       func = sort_reverse ? rev_cmp_version : compare_version;
       break;
+    case sort_dirsfirst:
+      func = sort_reverse ? rev_cmp_dirsfirst : compare_dirsfirst;
+      break;
     default:
       abort ();
     }
@@ -2265,7 +2284,7 @@
 static int
 compare_name (const struct fileinfo *file1, const struct fileinfo *file2)
 {
-  return strcoll (file1->name, file2->name);
+  return strcmpfunc (file1->name, file2->name); //strcoll
 }
 
 static int
@@ -2317,6 +2336,22 @@
   return cmp;
 }
 
+static int
+compare_dirsfirst (const struct fileinfo *file1, const struct fileinfo *file2)
+{  
+  if (S_ISDIR(file1->stat.st_mode) == S_ISDIR(file2->stat.st_mode))
+    return compare_name (file1, file2);
+  return S_ISDIR(file1->stat.st_mode) ? -1 : 1;
+}
+
+static int
+rev_cmp_dirsfirst (const struct fileinfo *file2, const struct fileinfo *file1)
+{
+  if (S_ISDIR(file1->stat.st_mode) == S_ISDIR(file2->stat.st_mode))
+    return compare_name (file1, file2);
+  return S_ISDIR(file1->stat.st_mode) ? -1 : 1;
+}
+
 /* List all the files now in the table.  */
 
 static void
@@ -3268,6 +3303,7 @@
                                types.  WHEN may be `never', `always', or `auto'\n\
   -d, --directory            list directory entries instead of contents\n\
   -D, --dired                generate output designed for Emacs' dired mode\n\
+  -e                         sort alphabetically with 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\
@@ -3284,6 +3320,7 @@
       --indicator-style=WORD append indicator with style WORD to entry names:\n\
                                none (default), classify (-F), file-type (-p)\n\
   -i, --inode                print index number of each file\n\
+  -j                         sort alphabetically, ranging in noncapitals\n\
   -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\n\
   -k, --kilobytes            like --block-size=1024\n\
   -l                         use a long listing format\n\
@@ -3307,7 +3344,7 @@
       printf (_("\
   -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\

Reply via email to