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\