5
$\begingroup$

Currently there are a list of notebooks in Windows that I am processing in a folder. Ideally I would like the notebooks to be concated in the same order as how they display in Windows Explorer.

I found the question Sort Strings By Natural Order, but none of the answers seem to use the same technique as Windows Explorer. After reading What is the first character in the sort order used by Windows Explorer?, it appears that Windows has an internal function that could be used to naturally sort the filenames. I plan to run this only on Windows, so it is okay if it depends on OS-specific functions, though a pure Mathematica way would be nice.

I believe that Windows sorts the files based on ASCII order unless a number is encountered. Ideally I am looking for a function that sorts a list of names into the following order when run. None of the answers linked above correctly order the names below.

{"Ie4 01", "Ie4!01", "Ie4_01", "Ie4_128", "Ie5", "Ie6", "Ie401sp2", 
 "Ie501sp2"}
Ie4 01
Ie4!01
Ie4_01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2
$\endgroup$
5
  • 2
    $\begingroup$ Could you perhaps specify the kind of ordering you are after to make the question self-contained? $\endgroup$
    – Yves Klett
    Commented Dec 27, 2013 at 10:42
  • 4
    $\begingroup$ (1) Please include some example strings/names where the Windows ordering does not match the ordering given by methods in the linked Q&A. (2) How robust does this need to be? Since you don't want to use the Windows sorting itself you are asking for a reimplementation of that sort ordering, and unless the exact specification is available it will be hard to confirm that it is entirely uniform. $\endgroup$
    – Mr.Wizard
    Commented Dec 27, 2013 at 11:50
  • $\begingroup$ @YvesKlett I have added an example which I believe demonstrates all the necessary issue encountered with the linked Q&As. $\endgroup$
    – William
    Commented Dec 27, 2013 at 18:59
  • $\begingroup$ You can call the DLL function that does the sorting: msdn.microsoft.com/en-us/library/bb759947%28VS.85%29.aspx $\endgroup$
    – Ajasja
    Commented Dec 27, 2013 at 19:25
  • $\begingroup$ @Mr.Wizard I Added an example which I believe demonstrates the issue that are encountered with the linked Q&As. I striked through the restraint of using Windows sorting because I'm not particularly concerned about running the script on Linux or OSX. $\endgroup$
    – William
    Commented Dec 27, 2013 at 20:07

1 Answer 1

10
$\begingroup$

You can call the windows function that does the sorting directly. The function is StrCmpLogicalW. Note that this is not a cross-platform solution:)

Here is a short example:

Needs["NETLink`"];
naturalOrder = 
  DefineDLLFunction["StrCmpLogicalW", "Shlwapi.dll", 
   "int", {"string", "string"}, MarshalStringsAs -> "Unicode"];

strings = {"Ie501sp2", "Ie4!01", "Ie4 01", "Ie4_01", 
   "Ie4_128", "Ie5", "Ie6", "Ie401sp2"};
Sort[strings, naturalOrder[#1, #2] == -1 &] //Column

(*
Ie4 01
Ie4!01
Ie4_01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2
*)
$\endgroup$
6
  • $\begingroup$ Great except it doesn't seem to match Windows Explorer. :) I have no idea why just yet. $\endgroup$
    – William
    Commented Dec 27, 2013 at 20:42
  • $\begingroup$ The hat becomes you (^_-) $\endgroup$
    – Yves Klett
    Commented Dec 27, 2013 at 20:45
  • $\begingroup$ I just tried all StrCmp on this page. Map[( naturalOrder = DefineDLLFunction[#, "Shlwapi.dll", "int", {"string", "string"}]; strings = FileNames[]; Sort[strings, naturalOrder[#1, #2] == 1 &]) &, {"StrCmpW", "StrCmpCW", "StrCmpIW", "StrCmpICW", "StrCmpLogicalW", "StrCmpNW", "StrCmpNCW", "StrCmpNIW", "StrCmpNICW"} ] Non of them seem to match. $\endgroup$
    – William
    Commented Dec 27, 2013 at 21:00
  • $\begingroup$ @LiamWilliam Sorry, forgot the MarshalStringsAs option. $\endgroup$
    – Ajasja
    Commented Dec 27, 2013 at 21:30
  • $\begingroup$ @YvesKlett Hehe, thanks. It does look kind of regal, doesn't it:) $\endgroup$
    – Ajasja
    Commented Dec 27, 2013 at 22:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.