Windows的“dir”命令,按名称排序和<某个东西>

4
我们可以在Windows资源管理器中按名称排序查看目录中的文件。
如果我在Windows命令提示符中尝试同样的操作,它会按不同的方式(正确地)按名称排序:
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, ...

有没有一种方法可以让 dir 按名称排序,使它读取数字时像人类一样?

Jeff Atwood在这篇博客文章中讨论了这个问题:http://www.codinghorror.com/blog/archives/001018.html - Jon Limjap
@JonLimjap 这个链接重定向到Jeff的博客主页了?! - steenhulthin
@steenhulthin 真是个震撼消息!!Atwood 决定改变他的想法,结果却让每个人都受到了影响。 - Keng
1
@steenhulthin 抱歉,这是一条五年前的评论,所以链接可能已经失效。更新后的链接在这里:http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ - Jon Limjap
7个回答

9

如果可能的话,您最好的选择是为较小的数字添加足够的前导零(在这种情况下为两个),以便排序按预期进行。


4
如果我曾经预计需要按顺序处理文件,我会在前面加上1到4个前导零或使用完整的UTC格式时间戳,如20081028143531。这是一个旧技巧,可以追溯到70年代末或80年代初,甚至可能更早。 - Ken Gentle
有没有类似DIR的免费软件,可以将所需文件列表自然排序并输出到文本文件中? - Andrey Kazak

5
Windows Explorer使用特殊的排序函数StrCmpLogicalW,而cmd.exe不使用它,因此输出结果有所不同。不过您可以使用它编写自己的排序程序。
您可能也会对Michael Kaplan在Raymond Chen的suggestion box上关于this subject的条目感兴趣。

2
那被称为自然排序。目前没有内置的命令行工具可以进行自然排序。如果你想的话,请投票支持该功能,让微软改变他们的想法。
不过,可以通过正则表达式替换来模拟这个过程,给数字添加零以使其长度相同。这样,字典排序就等同于自然排序。在Windows上,你可以使用Jscript和VBS来实现。但最简单的方法是使用PowerShell:
(Get-ChildItem | Sort-Object { [regex]::Replace($_.Name, '\d+', { $args[0].Value.PadLeft(20) }) }).Name

你可以在cmd.exe中这样调用它。
powershell -Command "(Get-ChildItem | Sort-Object { [regex]::Replace($_.Name, '\d+', { $args[0].Value.PadLeft(20) }) }).Name"

当然,如果你的文件包含更长的数字序列,你需要在PadLeft(20)中更改数字。
如果你想以与Windows资源管理器相同的方式按文件名排序,可以参考如何按文件名排序?
如果你的文件只有一个数字结尾,并且想使用批处理解决方案,可以查看批处理中的自然排序文件
@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

0
我前几天需要处理一个已排序的文件夹,这些答案帮助我得到了我所需的结果。我的问题是,我需要对文件夹名称进行排序,而它们的格式是XXX99.9.99.99。Windows自然会正确地对它们进行排序。然而,DIR命令却不会,因为其中一些数字是个位数,而另一些数字是两位或三位数。在我的批处理文件中,我将DOS FOR命令与调用powershell结合起来,使用了这里提供的答案: 如何按照与Windows资源管理器相同的方式按文件名排序? 最初,我是使用DIR进行排序的,但后来数字格式发生了变化。
FOR /f "tokens=*" %%a in ('dir /o:-n /b /ad %SourceFolder%\%SourceFolderMask%*.*.*.*') DO SET "lastFolder=%%~a" & GOTO :foundFolder

我所需要的只是最新的文件夹名称,并且通过-n排序结合GOTO,一切都很顺利,直到出现问题。
然后,我能够使用调用PowerShell的自定义脚本文件来获取我所需的内容,但由于列表是按升序排序的,我不得不对我的用法进行了轻微的更改。
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

如果ps1脚本更新以允许逆向排序,那么我可以回到之前的例子中,通过使用DO ... & GOTO提前退出FOR循环。

-1
我使用一个叫做ImageMagick的程序将我的200MB PDF文件转换成JPG格式。在这个漫长的过程结束时,它会按照数字顺序对所有文件进行序列化...因此,随着每个文件被写入硬盘,文件创建日期的值会略微增加。因此,以下两个批处理命令中的任何一个都可以按照“正确”的顺序写入文件:
dir *.jpg /ODN /B > files.txt

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

因此,dir *.jpg /OD 命令按升序(创建?)日期对目录内容进行排序,我们可以完全忽略实际文件名。

3
我很确定“dir /od”命令使用的是最后修改日期而不是创建日期。如果想使用创建日期,需要使用“dir /tc /od”命令。 - system PAUSE

-1

不,没有办法做到这一点。Windows资源管理器使用不同的方法来处理此问题。


-2

来自JPSoft的4NT/TCC/TC默认使用自然排序。或者,如果您可以访问GNU sort程序,例如Cygwin工具,您可以执行类似于ls -1 | /<cygwin>bin/sort -gdir /b | \cygwin\bin\sort -g的操作;这将按自然排序顺序给出文件名。

如果您受限于仅使用Windows本地工具,则可以尝试使用Windows脚本工具并执行类似于使用FileSystemObject获取文件名和正则表达式提取文件名中的数字部分以用作字典对象中的键。我将把实际编码留给读者作为练习 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接