4

We can see in a directory files ordered by Name in Windows Explorer.

If I try the same thing in the Windows command prompt it orders by name differently - correctly:

dir *.jpg /ON /B

cubierta.jpg
pag00.jpg
pag06.jpg
pag08.jpg
pag09.jpg
pag100.jpg
pag101.jpg
pag102.jpg
pag103.jpg
pag104.jpg
pag105.jpg
pag106.jpg
pag107.jpg
pag108.jpg
pag109.jpg
pag11.jpg, etc, etc, etc, ...

Is there a way to get dir to order by Name where it reads the numbers as a human would do?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
ian_scho
  • 5,906
  • 9
  • 35
  • 51
  • Jeff Atwood discussed this in a blog post here: http://www.codinghorror.com/blog/archives/001018.html – Jon Limjap Oct 28 '08 at 11:15
  • @JonLimjap The link redirects to the main page of Jeff's blog?! – steenhulthin May 06 '14 at 07:10
  • @steenhulthin SHOCKER!! Atwood decides to change his mind about something and screws everyone in the process. – Keng May 06 '14 at 14:02
  • 1
    @steenhulthin Sorry, it's a 5 year old comment so the link would probably be stale. The updated link is here: http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ – Jon Limjap May 06 '14 at 14:21

7 Answers7

9

Your best option (if possible) is to add enough leading zeros (two, in this case) to your smaller numbers so that the sort does come out as expected.

Doug L.
  • 2,676
  • 1
  • 19
  • 33
  • 4
    If I _ever_ anticipate needing to process files in order, I pad with 1 to 4 leading zeros or use a complete UTC format timestamp, 20081028143531. This is an *old* trick, dating back to the late '70s or early 80s. Maybe before then... – Ken Gentle Oct 28 '08 at 14:17
  • Is there a freeware analogue of DIR to output the desired file list sorted naturally to a text file? – Andrey Kazak Apr 15 '22 at 06:18
5

Windows Explorer uses a special sorting function, StrCmpLogicalW, which is not used by cmd.exe, hence the differences in the output. You could write your own sorting program with it, though.

You might also be interested in Michael Kaplan's entries on this subject (from Raymond Chen's suggestion box).

phuclv
  • 37,963
  • 15
  • 156
  • 475
Rômulo Ceccon
  • 10,081
  • 5
  • 39
  • 47
2

That's called a natural sort. Currently there are no built-in command line tools that can sort naturally. If you want please vote for the feature to make Microsoft change their mind

This however can be simulated with a regex replacement to pad zeros to make numbers have the same length. That way a lexicographic sort is equivalent to a natural sort. On Windows you can use Jscript and VBS to do that. But the easiest way is using powershell:

(Get-ChildItem | Sort-Object { [regex]::Replace($_.Name, '\d+', { $args[0].Value.PadLeft(20) }) }).Name

You can call it from cmd.exe like this

powershell -Command "(Get-ChildItem | Sort-Object { [regex]::Replace($_.Name, '\d+', { $args[0].Value.PadLeft(20) }) }).Name"

Of course you'll need to change the number in PadLeft(20) if your files contain a longer series of digits

How to sort by file name the same way Windows Explorer does?

A native batch solution can be found in Naturally Sort Files in Batch if your files have only a single number at the end

@echo off
setlocal enabledelayedexpansion
for %%a in (*.txt) do (
    set num=00000000000000000000%%a
    set num=!num:~-20!
    set $!num!=%%a
)
for /f "tokens=1,* delims==" %%a in ('set $0') do echo %%b
phuclv
  • 37,963
  • 15
  • 156
  • 475
0

I just had a need to process a sorted folder the other day and these answers helped me get what I needed. My issue was that I needed to sort folder name and they were in the format XXX99.9.99.99. Windows, naturally, sorted them correctly. However, DIR did not since some of the numbers were single digits and some were double/triple digits. In my batch file, I combined the DOS FOR command with a call out to powershell using the answer provided here: How to sort by file name the same way Windows Explorer does?

Originally, I was sorting using DIR, but then the number format changed.

FOR /f "tokens=*" %%a in ('dir /o:-n /b /ad %SourceFolder%\%SourceFolderMask%*.*.*.*') DO SET "lastFolder=%%~a" & GOTO :foundFolder

All I needed was the newest folder name and with the sort by -n combined with a GOTO, it all worked nicely, until it didn't.

I was able to then use the call to powershell with a custom script file to get what I needed, however, because the list is sorted ascending, I had to make a slight change in my usage.

FOR /f "tokens=*" %%a in ('powershell -Command "C:\_sc\OS\Main\NaturalSort1.ps1; $array = Get-ChildItem -Name -Attribute directory -Path %SourceFolder%;[NaturalSort]::Sort($array)"') DO SET "lastFolder=%%~a"
GOTO :foundFolder

If the ps1 script gets updated to allow reverse sorting, then I can revert back to my previous example of exiting the FOR early with the DO ... & GOTO

dashrader
  • 317
  • 3
  • 14
-1

No, there's no way to do this. Windows Explorer uses a different approach to handle this.

Biri
  • 7,101
  • 7
  • 38
  • 52
-1

I use a program called ImageMagick to convert my 200MB PDF files to JPG. At the end of the lengthy process it serializes all of the files in numerical order... So basically the file creation date increases in value slightly as each file is being written to the hard drive. Thus either of the following two batch file commands will write the files in the 'correct' order:

dir *.jpg /ODN /B > files.txt

for /f "tokens=*" %%a in ('dir *.jpg /ODN /B') do (
    echo ^<page^>%%a^</page^> >>pages.xml.fragment
)

Thus the dir *.jpg /OD command orders the directory content by ascending (creation?) date, and we can completely ignore the actual file name.

Doug L.
  • 2,676
  • 1
  • 19
  • 33
ian_scho
  • 5,906
  • 9
  • 35
  • 51
  • 3
    I'm pretty sure that last-modification date (not creation date) is used for 'dir /od'. For creation date, you need 'dir /tc /od'. – system PAUSE Apr 03 '09 at 14:39
-2

4NT/TCC/TC from JPSoft use natural sort order by default. Alternatively, if you have access to a GNU sort program, such as the Cygwin tools, you can do something like ls -1 | /<cygwin>bin/sort -g or dir /b | \cygwin\bin\sort -g; that will give you the filenames in natural sort order.

If you are constrained to tools that are native to Windows, you can try the Windows Scripting tools and do something like use a FileSystemObject to get the filenames, and regular expressions to extract the numeric part of the filenames to use as keys in a Dictionary object. I'll leave the actual coding as an exercise to the reader :)

phuclv
  • 37,963
  • 15
  • 156
  • 475