@@ -432,13 +432,14 @@ static enum time_type time_type;
432432
433433enum  sort_type 
434434  {
435-     sort_none  =  -1 ,		/* -U */ 
436-     sort_name ,			/* default */ 
437-     sort_extension ,		/* -X */ 
438-     sort_size ,			/* -S */ 
439-     sort_version ,		/* -v */ 
440-     sort_time ,			/* -t */ 
441-     sort_numtypes 		/* the number of elements of this enum */ 
435+     sort_none  =  -1 ,     /* -U */ 
436+     sort_name ,          /* default */ 
437+     sort_extension ,	    /* -X */ 
438+     sort_size ,          /* -S */ 
439+     sort_version ,       /* -v */ 
440+     sort_time ,          /* -t */ 
441+     sort_alphanumeric ,  /* -Y */ 
442+     sort_numtypes        /* the number of elements of this enum */ 
442443  };
443444
444445static  enum  sort_type  sort_type ;
@@ -853,11 +854,11 @@ ARGMATCH_VERIFY (format_args, format_types);
853854
854855static  char  const  * const  sort_args [] = 
855856{
856-   "none" , "time" , "size" , "extension" , "version" , NULL 
857+   "none" , "time" , "size" , "extension" , "version" , "alphanumeric" ,  NULL 
857858};
858859static  enum  sort_type  const  sort_types [] = 
859860{
860-   sort_none , sort_time , sort_size , sort_extension , sort_version 
861+   sort_none , sort_time , sort_size , sort_extension , sort_version ,  sort_alphanumeric 
861862};
862863ARGMATCH_VERIFY  (sort_args , sort_types );
863864
@@ -1838,6 +1839,11 @@ decode_switches (int argc, char **argv)
18381839          sort_type_specified  =  true;
18391840          break ;
18401841
1842+         case  'Y' :
1843+           sort_type  =  sort_alphanumeric ;
1844+           sort_type_specified  =  true;
1845+           break ;
1846+ 
18411847        case  '1' :
18421848          /* -1 has no effect after -l.  */ 
18431849          if  (format  !=  long_format )
@@ -3265,12 +3271,58 @@ cmp_extension (struct fileinfo const *a, struct fileinfo const *b,
32653271  return  diff  ? diff  : cmp  (a -> name , b -> name );
32663272}
32673273
3274+ /* Compare alphanumerically. That is, strings are sorted by their 
3275+    alphanumeric components, with numeric components sorted numerically. 
3276+    For example, "foo9" comes before "foo10".   
3277+     
3278+    Sort code from https://stackoverflow.com/a/1344056/338803  */ 
3279+ 
3280+ static  inline  bool 
3281+ isdigit (char  c )
3282+ { 
3283+   return  '0'  <= c  &&  c  <= '9' ;
3284+ }
3285+ 
3286+ static  inline  int 
3287+ cmp_alphanumeric  (struct  fileinfo  const  * a , struct  fileinfo  const  * b ,
3288+                   int  (* cmp ) (char  const  * , char  const  * ))
3289+ {
3290+   char  * s1  =  a -> name ;
3291+   char  * s2  =  b -> name ;
3292+ 
3293+   for  (;;) {
3294+     if  (* s2  ==  '\0' )
3295+       return  * s1  !=  '\0' ;
3296+     else  if  (* s1  ==  '\0' )
3297+       return  1 ;
3298+     else  if  (!(isdigit (* s1 ) &&  isdigit (* s2 ))) {
3299+       if  (* s1  !=  * s2 ) {
3300+         char  str1 [2 ] =  {* s1 , '\0' };
3301+         char  str2 [2 ] =  {* s2 , '\0' };
3302+         return  cmp  (str1 , str2 );
3303+       } else 
3304+         (++ s1 , ++ s2 );
3305+     } else  {
3306+       char  * lim1 , * lim2 ;
3307+       unsigned long  n1  =  strtoul (s1 , & lim1 , 10 );
3308+       unsigned long  n2  =  strtoul (s2 , & lim2 , 10 );
3309+       if  (n1  >  n2 )
3310+         return  1 ;
3311+       else  if  (n1  <  n2 )
3312+         return  -1 ;
3313+       s1  =  lim1 ;
3314+       s2  =  lim2 ;
3315+     }
3316+   }  
3317+ }
3318+ 
32683319DEFINE_SORT_FUNCTIONS  (ctime , cmp_ctime )
32693320DEFINE_SORT_FUNCTIONS  (mtime , cmp_mtime )
32703321DEFINE_SORT_FUNCTIONS  (atime , cmp_atime )
32713322DEFINE_SORT_FUNCTIONS  (size , cmp_size )
32723323DEFINE_SORT_FUNCTIONS  (name , cmp_name )
32733324DEFINE_SORT_FUNCTIONS  (extension , cmp_extension )
3325+ DEFINE_SORT_FUNCTIONS  (alphanumeric , cmp_alphanumeric )
32743326
32753327/* Compare file versions. 
32763328   Unlike all other compare functions above, cmp_version depends only 
@@ -4700,6 +4752,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
47004752  -w, --width=COLS           assume screen width instead of current value\n\ 
47014753  -x                         list entries by lines instead of by columns\n\ 
47024754  -X                         sort alphabetically by entry extension\n\ 
4755+   -Y                         sort alphanumerically\n\ 
47034756  -Z, --context              print any SELinux security context of each file\n\ 
47044757  -1                         list one file per line\n\ 
47054758" ), stdout );
0 commit comments