Get files from directory sorted by name

Dr.No jckj33 at gmail.com
Thu Apr 26 16:58:46 UTC 2018


On Wednesday, 25 April 2018 at 18:06:07 UTC, Jonathan M Davis 
wrote:
> On Wednesday, April 25, 2018 17:34:41 Dr.No via 
> Digitalmars-d-learn wrote:
>> Is there something implemented already to get the files from 
>> directory by name using D or I'm on my own and I have to write 
>> it myself? I didn't find how do that with dirEntries()
>
> There is nothing in the standard library for doing it, though 
> maybe someone has something on code.dlang.org. However, the 
> underlying OS API doesn't exactly conform well to that 
> particular use case. AFAIK, given how the C APIs work, the only 
> option is to get the list of files and then sort it, which 
> could be done easily enough with dirEntries. Something as 
> simple as
>
> auto files = dirEntries(dir, SpanMode.shallow).array();
> sort!((a, b) => a.name < b.name)(files);
>
> would give you a sorted DirEntry[] of all of the directories 
> and files directly in the directory. SpanMode.depth or 
> SpanMode.breadth could be used instead if you want 
> sub-directories, and std.algorithm.iteration.filter could be 
> used if you want to do something like filter out directories. 
> std.algorithm.iteration.map could be used if you just want the 
> file names. So, if you wanted just the names, you could do
>
> auto files = dirEntries(dir, SpanMode.shallow).map!(a => 
> a.name)().array();
> sort(files);
>
> though you'd need to use std.path.baseName if you didn't want 
> the full path
> - e.g. map!(a => a.name.baseName)(). If you wanted just files, 
> you could do
> something like
>
> auto files = dirEntries(dir, SpanMode.shallow).
>              filter!(a => a.isFile()).array();
> sort!((a, b) => a.name < b.name)(files);
>
> or
>
> auto files = dirEntries(dir, SpanMode.shallow).
>              filter!(a => a.isFile()).map!(a => a.name).array();
> sort(files);
>
> Exactly which combination of functions you use depends on what 
> you want for the end result. But the key thing is that you use 
> std.array.array to convert the forward range into a dynamic 
> array so that std.algorithm.sorting.sort can sort it (since it 
> requires a random-access range). I really don't think that 
> you're going to find any other way to do this other than 
> someone who has written a function that just ends up doing the 
> same thing by wrapping a call to dirEntries or the underlying C 
> API.
>
> - Jonathan M Davis

I have had just called sort, to later realize the sort wasn't in 
the way humans expect (which is the way Windows Explorer does) so 
I eventually reached 
https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ but I failed to call StrCmpLogicalW() from core.sys.windows.shlwapi or link on my own:

pragma(lib, "Shlwapi.lib")
extern(Windows) int StrCmpLogicalW(
   PCWSTR psz1,
   PCWSTR psz2
);

but I got links error so I went to implement StrCmpLogicalW() on 
my own and sorted like this:

auto files = dirEntries(inputDir, SpanMode.shallow).array();
// natural sort
sort!((a, b) => StrCmpLogical(a, b) < 0)(files);

which resulted in the files in same way as Windows 
Explorer/Natural sort.





More information about the Digitalmars-d-learn mailing list