The API function used to compare the file names is StrCmpLogicalW which is not accessible in Batch. However, we can use Batch to call Powershell that wraps a C# class that imports Windows API functions, and use it.
References:
https://docs.microsoft.com/en-us/window ... mplogicalw
https://docs.microsoft.com/en-us/dotnet ... comparer-1
Fully commented macro code:
Code: Select all
:: %logicalsort_asc% and %logicalsort_desc% macros
:: sort a list of lines in an Explorer-like manner
:: strings are read from standard input and written to standard output
set logicalsort_asc=powershell -nop -ep Bypass -c ^"try{ %======================== invoke Powershell with the code specified after -c =%^
%=% Add-Type ' %================================================================== add a .NET class to the Powershell session =%^
%=====% using System.Runtime.InteropServices; %=================================== namespace used for platform invokation =%^
%=====% public class SCmpLgcl : System.Collections.Generic.IComparer^<string^>{ %= custom comparer class for a List of string =%^
%=========% [DllImport(\"shlwapi.dll\",CharSet=CharSet.Unicode)] %================ import StrCmpLogicalW which is the comparison function used =%^
%=========% static extern int StrCmpLogicalW(string a,string b); %=============== to sort Windows Explorer list views =%^
%=========% public SCmpLgcl(){} %================================================= public constructor of the comparer class =%^
%=========% public int Compare(string a,string b){return StrCmpLogicalW(a,b);} %== public Compare method of the comparer that calls StrCmpLogicalW =%^
%=====% }'; %===================================================================== end of the .NET class =%^
%=% $list=[System.Collections.Generic.List[string]]@($Input); %=================== cast the standard input to a List of string =%^
%=% $list.Sort([SCmpLgcl]::new()); %============================================== invoke the Sort method of the List using an instance of the comparer class =%^
%=% $list; %====================================================================== write the sorted List to the standard output =%^
%=% exit 0;}catch{exit 1;}^" %==================================================== return a suitable errorlevel =%
(set logicalsort_desc=%logicalsort_asc:(a,b)=(b,a)%) %============================ reversed parameters passed to StrCmpLogicalW lead to descending sorting =%
Code: Select all
@echo off &setlocal
:: %logicalsort_asc% and %logicalsort_desc% macros
:: sort a list of lines in an Explorer-like manner
:: strings are read from standard input and written to standard output
set logicalsort_asc=powershell -nop -ep Bypass -c ^"try{^
%=% Add-Type '^
%=====% using System.Runtime.InteropServices;^
%=====% public class SCmpLgcl : System.Collections.Generic.IComparer^<string^>{^
%=========% [DllImport(\"shlwapi.dll\",CharSet=CharSet.Unicode)]^
%=========% static extern int StrCmpLogicalW(string a,string b);^
%=========% public SCmpLgcl(){}^
%=========% public int Compare(string a,string b){return StrCmpLogicalW(a,b);}^
%=====% }';^
%=% $list=[System.Collections.Generic.List[string]]@($Input);^
%=% $list.Sort([SCmpLgcl]::new());^
%=% $list;^
%=% exit 0;}catch{exit 1;}^"
(set logicalsort_desc=%logicalsort_asc:(a,b)=(b,a)%)
:: write an example file
>"_to_sort.txt" (
echo a3b4
echo a11b15
echo a5b
echo a100b
echo a3b18
echo x1b
echo a11b6
echo a3b
echo a2b
echo a9b
)
echo just print to screen (ascending sorted)
<"_to_sort.txt" %logicalsort_asc%
echo(
echo or process the output in a FOR /F loop (descending sorted)
for /f "delims=" %%i in ('^<"_to_sort.txt" %logicalsort_desc%') do echo %%i
echo(
echo or redirect to a file (ascending once again)
<"_to_sort.txt" >"_sorted.txt" %logicalsort_asc%
type "_sorted.txt"
echo(
:: clean up
del "_to_sort.txt" "_sorted.txt"
pause
Output:
Code: Select all
just print to screen (ascending sorted)
a2b
a3b
a3b4
a3b18
a5b
a9b
a11b6
a11b15
a100b
x1b
or process the output in a FOR /F loop (descending sorted)
x1b
a100b
a11b15
a11b6
a9b
a5b
a3b18
a3b4
a3b
a2b
or redirect to a file (ascending once again)
a2b
a3b
a3b4
a3b18
a5b
a9b
a11b6
a11b15
a100b
x1b
Drücken Sie eine beliebige Taste . . .