我在一个目录中有许多 SQL 脚本,以数字为前缀,例如
目前,我可以用这个脚本遍历它们:
@ECHO OFF
FOR /r . %%F IN (*.sql) DO (
ECHO File:"%%F"
)
但是,由于Windows读取目录中文件的方式,10和11在2之前被读取,等等:
如何按前缀顺序遍历目录中的每个文件?
我在一个目录中有许多 SQL 脚本,以数字为前缀,例如
目前,我可以用这个脚本遍历它们:
@ECHO OFF
FOR /r . %%F IN (*.sql) DO (
ECHO File:"%%F"
)
但是,由于Windows读取目录中文件的方式,10和11在2之前被读取,等等:
如何按前缀顺序遍历目录中的每个文件?
下面的批处理文件在需要它的文件名中插入前导零。
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%f in ('dir /B *.sql') do (
set "filename=%%f"
if "!filename:~1,1!" equ "-" ren "%%f" "0%%f"
)
编辑:添加了新的解决方案
下面的批处理文件以正确的顺序显示文件而不重命名它们。
@echo off
setlocal EnableDelayedExpansion
rem Create an array with filenames in right order
for %%f in (*.sql) do (
for /F "delims=-" %%n in ("%%f") do (
set "number=00000%%n"
set "file[!number:~-6!]=%%f"
)
)
rem Process the filenames in right order
for /F "tokens=2 delims==" %%f in ('set file[') do (
echo %%f
)
替代方法!
这不是您问题的直接答案,但可能会达到相同的结果:
FOR /L %%i IN (1,1,11) DO FOR %%f IN (%%i-*.sql) DO ECHO %%f
据我所知,没有FOR
标志。
但是这里是使用某种奇怪的正则表达式的纯 PowerShell 解决方案。
或者您可以列出文件,对它们进行排序,将这些排序的路径以正确的顺序放置到文件中,然后读取。
第三种解决方案是尝试使用标准的 Windows Shell 命令和运算符构建一些排序功能。
编辑 - 使用 JSORT.BAT 的新简单解决方案
本机批处理 SORT 命令非常有限。我编写了一个方便的JSORT.BAT 排序实用程序,它提供了许多方便的功能,包括根据数值对带有数字的字符串进行排序的能力。JSORT.BAT 是纯脚本(混合 JScript/批处理),可在任何 Windows 机器上本地运行,无需任何 3rd 方 exe 文件。
您可以使用数字列出文件
dir /b /a-d *.sql^|jsort /n /i
如果要迭代结果,只需将命令放在 FOR /F 循环中
for /f "delims=" %%F in ('dir /b /a-d *.sql^|jsort /n /i') do echo %%F
完整的文档可从命令行使用jsort /?
.
早于 JSORT.BAT 的原始解决方案
可以在不修改文件名的情况下使用批处理执行您想要的操作,如果您使用名为 REPL.BAT 的混合 JScript/批处理实用程序,该实用程序在标准输入上执行正则表达式搜索和替换并将结果写入标准输出,则效率非常高。该实用程序是纯脚本,可在从 XP 开始的任何 Windows 机器上运行 - 不需要 3rd 方可执行文件。完整的文档嵌入在脚本中。
假设 REPL.BAT 在您的当前目录中,或者更好的是,在您的 PATH 中的某个位置,那么以下将以.sql
所需的排序顺序迭代以数字开头的文件。如前所述,它支持长达 5 位的数字。它可以轻松扩展以支持更大的数字。
@echo off
for /f "tokens=2 delims=:" %%F in (
'dir /b /a-d *.sql^|repl "^(\d+).*" "00000$1:$&" a^|repl ".*(\d{5}:)" "$1"^|sort'
) do echo %%F
这确实显示了管道的力量:)
复杂的 IN() 子句的工作方式如下:
父 FOR /F 然后读取结果,将原始文件名解析为第二个:
分隔标记。
根据需要使用前导 0 重命名脚本,以便前缀中的位数始终相同。
Take Command Console
是一个免费版本的命令解释器,会进行自然排序。
在批处理中使用 powershell 进行排序的示例:
FOR /f "usebackq" %%F IN (
`powershell "ls -r *.sql | sort { [int]($_.Name -replace '\D','') } | %% { $_.FullName }"`
) DO (
ECHO File:"%%F"
)
ls -r *.sql
(的缩写形式Get-ChildItem -Recurse
)对应于FOR /r . %%F IN (*.sql)
部分sort { [int]($_.Name -replace '\D','') }
在排序之前从文件名中提取数字%% { $_.FullName }
(的缩写形式ForEach-Object
)打印每个文件的完整路径