WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Arrays
plus
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

File Names in the Shell Like Sort Order

 Keywords:  file name filename sort sorting order sequence format list string ascending Windows shell explorer Quick Sort udfArrQuickRSort StrCmp lexicological

Question:

I need to process a list of files in file name sequence. The file name is in the format: filename##
Slide1.JPG
Slide10.JPG
Slide11.JPG
Slide12.JPG
Slide13.JPG
Slide14.JPG
Slide15.JPG
Slide16.JPG
Slide17.JPG
Slide18.JPG
Slide19.JPG
Slide2.JPG
Slide20.JPG
Slide21.JPG
Slide22.JPG
Slide23.JPG
Slide24.JPG
Slide25.JPG
Slide26.JPG
Slide27.JPG
Slide28.JPG
Slide29.JPG
Slide3.JPG
Slide30.JPG
Slide31.JPG
Windows displays the order in the right sequence when displaying the list in a window:
Slide1.JPG
Slide2.JPG
Slide3.JPG
Slide10.JPG
Slide11.JPG
Slide12.JPG
.......
How can I get the right sequence using WinBatch?

Answer:

WIL functions use either an intuitive sort or an dictionary sort.

ItemSort & AskItemlist - Sorts a list, using an "ANSI Collating Sequence" sort, also known as a "dictionary sort" or "word sort".

ArraySort - Sorts a list, using an "intuitive" sort. ArraySort uses its own unique comparison algorithm which is roughly equivalent to the the results of using the WIL relational operators. This means the sort is sensitive to data types but treats strings with a mix of alpha and numeric characters lexicologically. Not surprisingly, alpha mixed with numeric characters in file names is the main source of differences between the result you might see with ArraySort vs. the shell's UI sort.

The theory behind an "intuitive sort" is to sort a list in a way very similar to how a human might do it. Notes on intuitive sorts:

Because you are dealing with files names, you will always be sorting using Word values (which are "word sorted") also known as a "dictionary sort".

The following seems to match the order your are looking for. Details: Among other things the shell's string comparison function handles string with both alpha and numeric characters differently than either the CRT strcmp or the Windows lstrcmp functions, or the WinBatch relational operators. It treats strings that vary only by their numeric part numerically instead of lexically. This permits the quick sort UDF to sort file names the same way the Windows shell does.

#DefineFunction udfArrQuickRSort(Array) ; recursive
   If (VarType(Array)<>256) Then Return(Array)
   If (ArrInfo(Array,0)>1) Then Return(Array)
   arrmax = ArrInfo(Array,1) - 1
   If (arrmax<0) Then Return(Array)
   hShlwapi = DllLoad("Shlwapi")
   udfArrQRSort(Array,0,arrmax,hShlwapi)
   DllFree(hShlwapi)
   Return(Array)
#EndFunction

#DefineFunction udfArrQRSort(Array,left,right,hShlwapi)
   If (left<right)
      pivot = Array[(left + right) / 2]
      i = left
      k = right
      While(i<=k)
         While DllCall(hShlwapi,long:"StrCmpLogicalW", lpwstr:Array[i], lpwstr:pivot) < 0 ;(Array[i]
            i = i + 1
         EndWhile
         While DllCall(hShlwapi,long:"StrCmpLogicalW", lpwstr:pivot, lpwstr:Array[k]) < 0 ;(pivot
            k = k - 1
         EndWhile
         If (i<=k)
            A = Array[i]
            Array[i] = Array[k]
            Array[k] = A
            i = i + 1
            k = k - 1
         EndIf
      EndWhile
      udfArrQRSort(Array,left,k,hShlwapi)
      udfArrQRSort(Array,i,right,hShlwapi)
   EndIf
   Return(Array)
#EndFunction

;; Grab some files
;  Create a temporary list of files
; Word list
list = ''
For x = 1 To 20
   name = 'sample':x:'.txt'
   If list == '' Then list = name
   Else list = list : @TAB : name
Next

;;Numeric values
;list = ''
;for x = 1 to 20
;   name = Int('-':x)
;   if list == '' then list = name
;   else list = list : @tab : name
;next

;;Fileitemize
;list = FileItemize( 'c:\temp\*.*' )

aFiles = Arrayize(list, @TAB)


; Sort
udfArrQuickRSort(aFiles)

; Display
lSorted = ""
nLast = ArrInfo(aFiles, 1) - 1
For nRow = 0 To nLast
   lSorted = ItemInsert(aFiles[nRow], -1, lSorted, @TAB )
Next

strName = AskItemlist("File Names in the Shell Like Sort Order", lSorted, @TAB, @UNSORTED, @SINGLE)
Exit

Article ID:   W17661
Filename:   File Names in the Shell Like Sort Order.txt
File Created: 2013:03:12:07:59:20
Last Updated: 2013:03:12:07:59:20