2

我有以下批处理代码,它执行文件夹的所有 SQL 文件。

for /r %%G in (*.sql) do sqlcmd /S localhost /d superDB /U sa /P topsecret -i"%%G"
pause

但现在我只想执行名称以两位数开头的文件,例如:

01_file.sql
02_file.sql
05_file.sql
43_file.sql

但不是这样的文件:

optional_01_file.sql 
XYZ04_file.sql

有人可以告诉我如何更改代码以仅过滤文件名以 2 位数字开头的文件吗?

4

3 回答 3

3

Findstr 的基本 RegEx 功能足以匹配文件。
未经测试:

:: Q:\Test\2018\07\21\SO_51456661.cmd
@echo off
for /r %%G in (*.sql) do (
    Echo=%%~nG|Findstr "^[0-9][0-9]_" 2>&1>Nul && (
        echo sqlcmd /S localhost /d superDB /U sa /P topsecret -i"%%G"
    )
)

在包含这些文件的文件夹中

> dir /B *.sql
01_file.sql
0815_file.sql
55_file.sql
abc0855_file.sql

我得到这些命令(仅用于演示)

> SO_51456661.cmd
sqlcmd /S localhost /d superDB /U sa /P topsecret -i"Q:\Test\2018\07\21\01_file.sql"
sqlcmd /S localhost /d superDB /U sa /P topsecret -i"Q:\Test\2018\07\21\55_file.sql"
于 2018-07-21T13:55:06.010 回答
0

我建议以下批处理文件执行此任务:

@for /F "delims=" %%G in ('dir "%~dp0??_*.sql" /A-D-H /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /R "[0123456789][0123456789]"') do @sqlcmd.exe /S localhost /d superDB /U sa /P topsecret -i"%~dp0%%G"

此批处理文件期望以 *.sql 开头[0-9][0-9]_的文件与批处理文件存储在同一目录中,并且运行批处理文件的当前目录可以是任何目录,这对于将此批处理文件作为计划任务运行时很有未设置计划任务的选项。

要处理当前目录而不是批处理文件目录中的 *.sql 文件,只需删除%~dp0扩展为驱动器和批处理文件路径的两个匹配项。扩展的批处理文件路径字符串始终以反斜杠结尾。

两者%~dp0都可以替换为任何其他以反斜杠结尾的文件夹路径。

带有已使用选项的命令FOR在一个单独的命令进程中运行,该进程cmd /C在后台从命令行启动

dir "C:\Batch File Path\??_*.sql" /A-D-H /B /ON 2>nul | C:\Windows\System32\findstr.exe /B /R /C:[0123456789][0123456789]

命令DIR搜索

  • 只是非隐藏文件,因为/A-D-H(属性不是目录而不是隐藏)
  • 在批处理文件的目录中
  • 对于匹配通配符模式的文件??_*.sql
  • 并且只输出文件名+文件扩展名来处理STDOUT(标准输出),因为/B(裸格式)
  • 由于 . 按名称按字母顺序排列/ON

DIRcmd.exe已经运行的用于处理此批处理文件的内部命令。

DIR输出的错误消息在找不到与为处理STDERR(标准错误)而编写的标准匹配的任何文件名时被重定向2>nul到设备NUL以抑制它。

处理STDOUTDIR的输出被重定向到处理下一个命令的STDIN(标准输入)FINDSTR是一个外部命令,这意味着默认情况下在 Windows 系统目录中可用的控制台可执行文件。|

FINDSTR搜索从STDIN读取的行

  • 开始因为/B
  • 与字符串匹配[0123456789][0123456789]
  • 由于显式使用,它被解释为正则表达式搜索字符串/R

请参阅Windows FINDSTR 命令有哪些未记录的功能和限制?因为使用[0123456789][0123456789]而不是[0-9][0-9]因为[0-9]匹配¹²³使用代码页 Windows-1252 编码的三个字符的原因。

FINDSTR输出与仅应用于前两个字符的正则表达式匹配的所有行(= 文件名),以处理后台命令进程的STDOUT

FOR捕获这些文件名并逐行处理它们。delims=为字符串拆分定义一个空列表,以始终将文件的全名分配给循环变量G,即使 *.sql 文件名包含一个或多个空格。

另请阅读有关使用命令重定向运算符的 Microsoft 文章,了解|和的说明2>nul。当 Windows 命令解释器在执行命令FOR之前处理此命令行时,重定向运算符>|必须^FOR命令行上使用脱字符进行转义,以便在后台启动的单独命令进程中执行嵌入式命令行。dirfindstr

最好还指定sqlcmd.exe将此批处理文件作为计划任务运行的完整路径,以使批处理文件独立于PATH用于运行计划任务的环境(帐户)的环境变量。

是否只是 *.sql 文件在文件夹中以两位数和下划线开头,或者在文件夹及其所有子文件夹中递归地执行,这有点不清楚sqlcmd

这是上述批处理文件命令行的变体,用于运行[0-9][0-9]_从包含批处理文件的文件夹开始的整个文件夹树中的所有 *.sql:

@for /F "delims=" %%G in ('dir "%~dp0??_*.sql" /A-D-H /B /ON /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /R /C:"\\[0123456789][0123456789]_[^\\]*$"') do @sqlcmd.exe /S localhost /d superDB /U sa /P topsecret -i"%%G"

命令DIR还与选项一起使用,/S该选项导致也在子目录中搜索与通配符模式匹配的文件??_*.sql

DIR的输出随着文件名的变化而变化,/S现在以完整的文件路径输出。

出于这个原因,FINDSTR没有/B,并且正则表达式被修改为\\[0123456789][0123456789]_[^\\]*$只输出 *.sql 文件,文件名中以两位数字开头,与文件路径无关。

调用该命令sqlcmd只是%%G因为循环变量包含要使用的当前 SQL 文件的完整限定文件名(= 文件路径 + 文件名 + 文件扩展名)。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • dir /?
  • findstr /?
  • for /?
  • sqlcmd -?
于 2018-07-21T18:38:13.573 回答
0

我会使用按名称过滤文件findstr,如下所示:

for /F "delims=" %%G in ('
    dir /S /B /A:-D "*.sql" ^| ^
        findstr /I /R /C:"\\[0123456789][0123456789]_[^\\]*\.sql$"
') do (
    sqlcmd /S localhost /d superDB /U sa /P topsecret -i"%%G"
)
pause
于 2018-07-22T14:46:57.227 回答