Using StrCmpLogicalW to sort strings the way the shell does


I have various scripts which use the "dir" command to enumerate files and then act on the most recent file that meets certain criteria. I noticed that "dir" and the Windows shell sometimes have different orders.

For example, if I have a folder containing files { track1.mp3, track2.mp3, ..., track9.mp3, track10.mp3, track11.mp3 } then the Windows shell will enumerate them in the natural order, but "dir" will enumerate them in the rather strange order { track1.mp3, track10.mp3, track11.mp3, track2.mp3, ...}.

Windows provides the StrCmpLogicalW API which is smart enough to realize that track9.mp3 < track10.mp3, so I whipped up a quick shellsort.exe utility that takes its standard input, breaks it up into lines, sorts those lines according to StrCmpLogicalW, and prints the resulting lines on its standard output. For bonus points I gave it a -reverse command-line option to print the output in reverse order (although it would have been more in the "toolbox" spirit to create a separate reverse.exe.)

>dir /b
track1.mp3
track10.mp3
track11.mp3
track2.mp3
track3.mp3
track4.mp3
track5.mp3
track6.mp3
track7.mp3
track8.mp3
track9.mp3

>dir /b | shellsort -reverse
track11.mp3
track10.mp3
track9.mp3
track8.mp3
track7.mp3
track6.mp3
track5.mp3
track4.mp3
track3.mp3
track2.mp3
track1.mp3

As with my previous exercise to find the longest duplicated substring in a given text, most of the code is taken up in reading the contents of the standard input in an efficient way.

Source and binaries attached.

EDIT September 22 2015: moved source to github https://github.com/mvaneerde/blog/tree/master/shellsort

shellsort.zip

Comments (0)

Skip to main content