跳转到内容

Windows 批处理脚本

50% developed
来自维基教科书,开放世界中的开放书籍
(从 Windows 命令指南 重定向)

本书描述并展示了如何使用 Microsoft 提供的命令解释器 cmd.exe 及其关联的命令,以及如何为解释器编写 Windows 批处理脚本。cmd.exe 是所有基于 Windows NT 的操作系统的默认解释器,包括 Windows XP、Windows 7 和 Windows 10。

本书讨论了适用于基于 Windows NT 环境的现代 Windows 版本的 32 位 Windows 命令。它不讨论特定于 DOS 环境和基于 DOS 的操作系统的命令,例如 Windows 95、Windows 98 和 Windows Me,它们的 Microsoft 提供的命令解释器实际上是 DOS 程序,而不是 Win32 程序。

您可以使用 VER 命令找出正在运行的 Windows 版本。

本书首先介绍了 Windows NT 命令解释器的使用,以及它如何接收、解析和处理来自用户的命令。然后,它将介绍各种可用的命令。

要获取 Windows 命令及其简要摘要的完整列表,请在任何 Windows 计算机上打开命令提示符,并键入help。要查找有关特定命令的信息,请键入命令名称后跟 “/?”。

本书的主题也称为“批处理编程”,即使“批处理”不仅指 MS DOS 和 Windows 命令解释器的批处理文件。其他主题术语包括“批处理文件编程”、“批处理文件脚本”、“Windows 批处理命令”、“Windows 批处理文件”、“Windows 命令行”、“Windows 命令提示符”和“Windows shell 脚本”。

对于 Windows 脚本,cmd.exe 是一种遗留技术;现代等效项是 PowerShell,它基于 .NET,其用于管道的流是对象,而不是字符(字节)流。PowerShell 的功能远远超过 cmd.exe;PowerShell 具有完整编程语言的功能,包括变量的类型化内容、浮点运算、大整数、通过 .NET 类进行 GUI 编程等。尽管如此,cmd.exe 仍然适用于简单的脚本和命令行交互任务,通常提供更短的语法和更快的启动时间,并且可以与从其他操作系统熟悉的字符流管道一起使用。cmd.exe 可以通过从其他操作系统中已知的命令来增强;请参阅 #Unix 命令。另一个用于 Windows 脚本的替代方案是流行的 Python,它使用其 pywin32 和 wmi 库;但是,这需要安装。

使用 Windows 命令解释器

[编辑 | 编辑源代码]

命令行的解释方式

[编辑 | 编辑源代码]

将命令行解析为一系列命令是一个复杂的过程。主要有四个部分:

  1. 变量替换:扫描命令行以查找变量规范,找到的任何变量规范都将替换为这些变量的内容。
  2. 引用:特殊字符可以被引用,以消除其特殊含义。
  3. 语法:命令行根据语法被解析为一系列命令。
  4. 重定向:在执行序列中的单个命令之前,将应用重定向规范,并将其从命令行中删除。

变量替换

[编辑 | 编辑源代码]

命令行可以包含变量规范。这些规范包括一个 % 字符,后跟一个名称,然后是一个第二个 % 字符,除非该名称是 0 ... 9 中的数字或星号 *。

变量规范将被替换为以下值:

  • %varname%,例如 %PATH% 或 %USERNAME%,将被替换为命名环境变量的值。例如,%PATH% 将被替换为 PATH 环境变量的值。变量名称匹配不区分大小写:%PATH% 和 %path% 具有相同的效果。
  • %n for 0 <= n <= 9,例如 %0 或 %9,将被替换为调用批处理文件时传递给批处理文件的第 n 个参数的值,受 SHIFT 命令的任何后续修改的影响。例如:%2 将被替换为第二个批处理文件参数的值。在交互式使用中(在批处理之外),这种情况不会发生替换。
  • %* 将被替换为除 %0 之外的所有命令行参数的值,即使是超过索引 9 的参数。 SHIFT 命令不会影响 %* 的结果。另请参见 命令行参数。在交互式使用中(在批处理之外),这种情况不会发生替换。
特殊变量名称
[编辑 | 编辑源代码]

某些变量名称使用 SET 命令不可见。相反,它们可以通过 % 符号进行读取。要了解这些名称,请键入 "help set"。

特殊变量名称及其展开内容

名称 使用的替换值
%CD% 当前目录,如果它不是当前驱动器的根目录,则不以斜杠字符结尾。另请参见 #CD
%TIME% 系统时间,格式为 HH:MM:SS.mm,除非区域设置规定了其他格式。另请参见 #TIME
%DATE% 系统日期,以特定于本地化的格式显示。另请参见 #DATE
%RANDOM% 生成的伪随机数,介于 0 到 32767 之间。另请参见 #计算
%ERRORLEVEL% 最后执行的命令或最后调用的批处理脚本返回的错误级别。另请参见 #错误级别
%CMDEXTVERSION% cmd.exe 当前使用的命令处理器扩展的版本号。
%CMDCMDLINE% 启动当前 cmd.exe 时使用的命令行的内容。

链接

引用和转义

[编辑 | 编辑源代码]

您可以阻止控制命令语法的特殊字符具有其特殊含义,但百分号 (%) 除外。

  • 您可以用引号将包含特殊字符的字符串括起来。
  • 您可以在特殊字符之前立即放置脱字符号 (^),这是一个转义字符。在管道 (|) 后的命令中,您需要使用三个脱字符号 (^^^) 才能使其生效。

需要引用或转义的特殊字符通常是 <、>、|、& 和 ^。在某些情况下,! 和 \ 也可能需要转义。换行符也可以用脱字符号转义。

使用引号将字符串括起来时,引号会成为传递给调用的命令的参数的一部分。相反,使用脱字符号作为转义字符时,脱字符号不会成为传递给的参数的一部分。

百分号 (%) 是一种特殊情况。在命令行中,它不需要引用或转义,除非使用两个百分号来表示变量,例如 %OS%。但在批处理文件中,您必须使用双百分号 (%%) 才能产生一个百分号 (%)。将百分号括在引号中或在其前面加脱字符号无效。

示例

  • echo "Johnson & son"
    • 回显完整字符串,而不是在 & 字符处拆分命令行。引号也将回显。
  • echo Johnson ^& son
    • 如上所示,但在特殊字符和号之前使用脱字符号。不会回显任何引号。
  • echo Johnson & son
    • 不使用转义字符,因此 "son" 被解释为一个单独的命令,通常会导致错误消息,即找不到命令 son。
  • echo A ^^ B
    • 回显 A ^ B。脱字符号也需要转义,否则它将被解释为转义空格。
  • echo > NUL | echo A ^^^^ B
    • 回显 A ^ B。在管道之后,用于转义的脱字符号需要重复三次才能生效;第四个脱字符号是正在转义的脱字符号。
  • if 1 equ 1 ^
    echo Equal &^
    echo Indeed, equal
    • 回显这两个字符串。行尾的脱字符号会转义换行符,导致三行被视为一行。第一个脱字符号前的空格是必需的,否则 1 会与后面的 echo 结合,形成 1echo。
  • attrib File^ 1.txt
    • 不显示名为 "File 1.txt" 的文件的属性,因为空格的转义不起作用。使用引号,如 attrib "File 1.txt",可以正常工作。
  • echo The ratio was 47%.
    • 如果从批处理文件运行,则会忽略百分号。
  • echo The ratio was 47%%.
    • 如果从批处理文件运行,则百分号会输出一次。
  • set /a modulo=14%%3
    • 如果从批处理文件运行,则将 modulo 变量设置为 2,即 14 除以 3 的余数。使用单个 % 无效。
  • for %%i in (1,2,3) do echo %%i
    • 如果从批处理文件运行,则会输出 1、2 和 3。
  • echo %temp%
    • 即使从批处理文件运行,也会输出 temp 变量的内容。在批处理中使用百分号访问环境变量和传递的参数不需要转义。
  • echo ^%temp^%
    • 从命令行运行时,会逐字输出 %temp%。
  • echo %%temp%%
    • 从批处理文件运行时,会逐字输出 %temp%。
  • echo //comment line | findstr \//
    • 命令 FINDSTR 使用反斜杠 (\) 进行转义。与脱字符号不同,这在命令内部进行,命令 shell 无法识别。

链接

命令行根据语法被解析为一系列命令。在该语法中,简单命令可以组合形成管道,而管道又可以组合形成复合命令,最终可以转换为带括号的命令

简单命令只是一个命令名、命令尾部和一些重定向规范。简单命令的示例如下:dir *.txt > somefile.

管道是几个简单命令通过 "管道" 元字符 "|" 连接在一起,也称为 "竖线"。每个竖线之前的简单命令的标准输出通过管道连接到其后面的简单命令的标准输入。命令解释器并行运行管道中的所有简单命令。管道(包含两个简单命令)的示例如下:dir *.txt | more.

复合命令是一组由连接词分隔的管道。管道按顺序执行,一个接一个,连接词控制命令解释器是否执行下一个管道。复合命令(包含两个管道,而管道本身只是简单命令)的示例如下:move file.txt file.bak && dir > file.txt.

连接词

  • & - 无条件连接词。当前管道执行完毕后,始终执行下一个管道。
  • && - 正向条件连接词。如果当前管道以零退出状态执行完毕,则执行下一个管道。
  • || - 负向条件连接词。如果当前管道以非零退出状态执行完毕,则执行下一个管道。

带括号的命令是括在括号中的复合命令(即())。从语法的角度来看,这将复合命令转换为简单命令,其整体输出可以重定向。

例如:命令行( pushd temp & dir & popd ) > somefile会导致整个复合命令的标准输出( pushd temp & dir & popd )被重定向到 somefile

链接

重定向

[edit | edit source]

重定向规范在执行命令序列中的单个命令之前应用并从命令行中删除。重定向规范控制简单命令的标准输入、标准输出和标准错误文件句柄指向的位置。它们会覆盖可能由管道产生的对这些文件句柄的任何影响。(请参阅前一节有关命令语法的部分。)重定向符号 > 和 >> 可以加上前缀 1 表示标准输出(与没有前缀相同)或 2 表示标准错误。

重定向规范如下:

< filename
将标准输入重定向为从指定文件读取。
> filename
将标准输出重定向为写入指定文件,覆盖其先前内容。
>> filename
将标准输出重定向为写入指定文件,追加到其先前内容的末尾。
>&h
重定向到句柄 h,其中句柄可以是 0(标准输入)、1(标准输出)、2(标准错误)等等。
<&h
从句柄 h 重定向。

示例

  • dir *.txt >listing.log
    • 将 dir 命令的输出重定向到 listing.log 文件。
  • dir *.txt > listing.log
    • 与上面相同;文件名前面的空格没有区别。但是,如果在命令窗口中键入此命令,在键入 "> l" 后使用 Tab 键进行自动完成实际上可以工作,而使用 ">listing.log" 则无法工作。
  • dir *.txt 2>NUL
    • 将 dir 命令的错误重定向到无处。
  • dir *.txt >>listing.log
    • 将 dir 命令的输出重定向到 listing.log 文件,追加到文件。这样,在执行重定向命令之前文件的内容就不会丢失。
  • dir *.txt >listing.log 2>&1
    • 将 dir 命令的输出重定向到 listing.log 文件,以及错误消息。
  • dir *.txt >listing.log 2>listing-errors.log
    • 将 dir 命令的输出重定向到 listing.log 文件,并将错误消息重定向到 listing-errors.log 文件。
  • >myfile.txt echo Hello
    • 重定向可以在命令之前。
  • echo Hello & echo World >myfile.txt
    • 只有第二个 echo 被重定向。
  • (echo Hello & echo World) >myfile.txt
    • 两个 echo 的输出都被重定向。
  • type con >myfile.txt
    • 将控制台输入 (con) 重定向到文件。因此,允许用户输入多行,用户按 Control + Z 键结束。另请参阅 #用户输入
  • (for %i in (1,2,3) do @echo %i) > myfile.txt
    • 将循环的整个输出重定向到文件。
  • for %i in (1,2,3) do @echo %i > myfile.txt
    • 每次进入循环体时都会重新开始重定向,从而丢失除最新循环迭代之外的所有输出。

链接

如何执行命令

[edit | edit source]

(...)

批处理重新加载

[edit | edit source]

命令解释器在每次执行一行或括号组之后重新加载批处理的内容。

如果启动以下批处理并在启动后不久将“echo A”更改为“echo B”,则输出将为 B。

@echo off
ping -n 6 127.0.0.1 >nul & REM wait
echo A

单行上的内容很重要;在运行以下批处理后更改“echo A”不会产生任何影响

@echo off
ping -n 6 127.0.0.1 >nul & echo A

启动后更改对用 ( 和 ) 括起来的命令没有任何影响。因此,在启动以下批处理后更改“echo A”不会产生任何影响

@echo off
for /L %%i in (1,1,10) do (
  ping -n 2 127.0.0.1 >nul & REM wait
  echo A
)

对于任何其他包含,包括此包含,也是如此

@echo off
(
ping -n 6 127.0.0.1 >nul & REM wait
echo A
)

环境变量

[edit | edit source]

命令解释器进程的环境变量被其执行的任何(外部)命令的进程继承。一些环境变量由命令解释器本身使用。更改它们会改变其操作。

环境变量受 SETPATHPROMPT 命令的影响。

要取消设置变量,请将其设置为空字符串,例如“set myvar=”。

命令解释器从创建它的进程继承其初始环境变量集。例如,对于从桌面快捷方式调用的命令解释器,这将是 Windows 资源管理器。

命令解释器通常具有文本用户界面,而不是图形用户界面,因此不识别通知应用程序注册表中的环境变量模板已更改的 Windows 消息。更改控制面板中的环境变量会导致 Windows 资源管理器从注册表中的模板更新其自身环境变量,从而更改任何随后调用的命令解释器将继承的环境变量。但是,它不会导致正在运行的命令解释器从注册表中的模板更新其环境变量。

另请参阅 #变量替换

链接

COMSPEC

[edit | edit source]

COMSPEC 环境变量包含命令解释器程序文件的完整路径名。这只是从父进程继承的,因此间接地从注册表中环境变量模板的 COMSPEC 设置派生。

PATH 环境变量的值包含一个目录名称列表,由分号字符隔开。这是在定位要执行的外部命令的程序文件时按顺序搜索的目录列表。

PATHEXT

[edit | edit source]

PATHEXT 环境变量的值是一个文件名扩展列表,由分号 (;) 隔开。这是在定位要执行的外部命令的程序文件时按顺序应用的文件名扩展列表。

由“echo %PATHEXT%”打印的 PATHEXT 的示例内容

  • .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

通过将“.PL”添加到变量,可以确保 Perl 程序即使在没有“.pl”扩展名的情况下从命令行运行。因此,无需键入“mydiff.pl a.txt b.txt”,就可以键入“mydiff a.txt b.txt”。

在 Windows Vista 及更高版本中将“.PL”添加到变量

  • setx PATHEXT %PATHEXT%;.PL
    • 如果使用 Windows XP 中可用的“set”,则效果将是暂时的,并且仅影响当前控制台或进程。

链接

PROMPT

[edit | edit source]

PROMPT 环境变量控制命令解释器在显示提示时发出的文本。命令解释器在交互模式下提示输入新命令行时,或在批处理文件模式下回显批处理文件行时显示提示。

PROMPT 环境变量值中的各种特殊字符序列会导致在显示提示时产生各种特殊效果,如以下表格所示

字符 展开结果
$$ $ 字符本身
$A & 符号,即和号。这是一个便利,因为很难在 PROMPT 环境变量的值中使用 SET 命令放置一个字面量&
$B 垂直线 '|'(管道符号)
$C 左括号 '('
$D 当前日期
$E ESC(ASCII 码 27)
$F 右括号 ')'
$G 大于号 '>'
$H 退格键(删除前一个字符)
$L 小于号 '<'
$M 如果当前驱动器是网络驱动器,则链接到当前驱动器的远程名称;否则为空字符串。
$N 当前驱动器盘符
$P 当前驱动器盘符和完整路径
$Q '='(等于号)
$S ' '(空格字符)
$T 当前系统时间
$V Windows 版本号
$_ <CR>(回车符,又称“Enter”)
$+ pushd 目录堆栈中的项目数量一样多的加号 (+)

链接

开关

[edit | edit source]

大多数 Windows 命令提供开关,也称为选项,以指导其行为。

观察结果

  • 开关通常由单个字母组成;一些开关由多个字母的序列组成。
  • 开关前面是斜杠 (/),而不是像在某些其他操作系统中那样用减号 (-)。
  • 开关不区分大小写,而不是像在某些其他操作系统中那样区分大小写。
  • 如果将来自另一个操作系统的命令移植到 Windows(例如 grep),它通常会保留来自原始操作系统的选项约定,包括使用减号和区分大小写。

示例

  • dir /?
    • 输出帮助。此选项由许多命令提供。
  • dir /b /s
    • 以递归方式列出当前文件夹中的所有文件和文件夹。使用两个开关:b 和 s。
  • dir /bs
    • 不起作用;开关不能累积在单个斜杠后面。
  • findstr /ric:"id: *[0-9]*" File.txt
    • 与许多其他命令不同,findstr 允许在单个斜杠后累积开关。实际上,r、i 和 c 是单字母开关。
  • dir/b/s
    • 有效。在 dir 中,删除命令和第一个开关之间或开关之间的空格没有区别;因此,与 dir /b /s 相同。
  • tree/f/a
    • 无效,与 tree /f /a 不同。在 tree 中,空格分隔是强制性的。find/i/v 也不起作用。
  • dir /od
    • 开关字母 o 由单个字母进一步修改,该字母指定排序应按日期进行。字母 d 本身不是开关。类似的情况包括 dir /ad 和 more /t4。
  • dir /B /S
    • 开关不区分大小写,与其他一些操作系统不同。
  • sort /r file.txt
    • 以相反的顺序对文件进行排序。
  • sort /reverse file.txt
    • Sort 允许开关字符串的长度超过单个字母。
  • sort /reve file.txt
    • Sort 允许指定的开关字符串是开关完整长名称的子字符串。因此,与上面的相同。
  • sort /reva file.txt
    • 无效,因为“reva”不是“reverse”的子字符串。
  • taskkill /im AcroRd32.exe
    • Taskkill 要求 /im 使用多字母开关名称;缩短为 /i 无效。
  • java -version
    • Java 诞生于另一个操作系统系列的环境中,使用减号约定表示其开关,也称为选项。
  • grep --help
    • 如果安装了 GNU grep,则它要求多字母开关之前有两个连字符。

错误级别

[edit | edit source]

命令通常在执行结束时设置错误级别。在 Windows NT 及更高版本中,它是一个 32 位有符号整数;在 MS DOS 中,它曾经是一个从 0 到 255 的整数。关键词:返回值、退出代码、退出状态。

错误级别的传统含义

  • 0 - 成功
  • 非 0 - 失败
  • 设置的错误级别通常为正数。
  • 如果命令不区分各种失败类型,则失败时的错误级别通常为 1。

错误级别的用途

  • 可以使用 && 和 || 进行测试;另见 #语法
  • 可以使用 IF 进行测试。
  • 可以使用 ERRORLEVEL 变量访问该值。

示例

  • dir >NUL && echo Success
    • 只有在错误级别为零时才执行 && 后的部分。
  • color 00 || echo Failure
    • 只有在错误级别为非零时才执行 || 后的部分,无论是正数还是负数。
  • color 00 || (
      echo Failure
    )
    • 多行括号也能正常工作。
  • echo %ERRORLEVEL%
    • 输出错误级别而不改变它。
  • if %errorlevel% equ 0 echo 错误级别为零,表示成功。
  • if %errorlevel% neq 0 echo 错误级别为非零,表示失败。
  • if errorlevel 1 echo 错误级别 >= 1,表示通过正错误级别失败。
    • 不包含通过负错误级别失败的情况。注意“>=”部分:这与 if %errorlevel% equ 1 不同。
  • exit /b 1
    • 返回批处理文件,将错误级别设置为 1。
  • cmd /c "exit /b 10"
    • 在批处理文件中间或命令行上,将错误级别设置为 10。
  • (cmd /c "exit /b 0" && Echo Success) & (cmd /c "exit /b -1" || Echo Failure)
    • 如上所示,表明错误级别确实受到了影响。
  • (cmd /c "exit /b 0" & cmd /c "exit /b 1") || Echo Failure
    • 由 & 创建的链的错误级别是链中最后一个命令的错误级别。
  • cmd /c "exit /b -1" & if not errorlevel 1 echo Would-be success
    • “if not errorlevel 1”测试似乎测试成功,但对负数通过:它测试“非错误级别 >= 1”,即“错误级别 <= 0”。
  • set myerrorlevel=%errorlevel%
    • 记住错误级别以备后用。
  • set errorlevel=0
    • 应避免:掩盖内置的 errorlevel 变量。确保随后通过 %ERRORLEVEL% 的访问返回 0 而不是实际错误级别。
  • cmd /c "exit /b 0"
    if 1 equ 1 ( cmd /c "exit /b 1" & echo %errorlevel% )
    • 输出 0,因为 %errorlevel% 在 cmd /c "exit /b 1" 执行之前扩展。

链接

字符串处理

[edit | edit source]

获取非空变量的子字符串

set a=abcdefgh
echo %a:~0,1%   & rem from index 0, length 1; result: a
echo %a:~1,1%   & rem from index 1, length 1; result: b
echo %a:~0,2%   & rem from index 0, length 2; result: ab
echo %a:~1,2%   & rem from index 1, length 2; result: bc
echo %a:~1%     & rem from index 1 to the end; result: bcdefgh
echo %a:~-1%    & rem from index -1 (last char) to the end; result: h
echo %a:~-2%    & rem from index -2 (next-to-last) to the end; result: gh
echo %a:~0,-2%  & rem from index 0 to index -2, excl.; result: abcdef
echo %a:~0,-1%  & rem from index 0 to index -1, excl.; result: abcdefg
echo %a:~1,-1%  & rem from index 1 to index -1, excl.; result: bcdefg

测试子字符串包含

  • if not "%a:bc=%"=="%a%" echo yes
    • 如果变量 a 包含“bc”作为子字符串,则回显“yes”。
    • 此测试是一个使用字符串替换的技巧,将在下面讨论。
    • 如果变量包含引号,此测试将不起作用。

测试“以...开头”

if %a:~0,1%==a echo yes   & rem If variable a starts with "a", echo "yes".
if %a:~0,2%==ab echo yes  & rem If variable a starts with "ab", echo "yes".

字符串替换

set a=abcd & echo %a:c=%   & rem replace c with nothing; result: abd
set a=abcd & echo %a:c=e%  & rem replace c with e; result: abed; 
set a=abcd & echo %a:*c=%  & rem replace all up to c with nothing; result: d
rem Above, the asterisk (*) only works at the beginning of the sought pattern.

另见 SET 命令的帮助:set /?。

通过“ ”、“,”和“;”中的任何一个拆分字符串:[“空格”、“逗号”和“分号”:]

set myvar=a b,c;d
for %%a in (%myvar%) do echo %%a

通过分号拆分字符串,假设字符串不包含引号

@echo off
set myvar=a b;c;d
set strippedvar=%myvar%
:repeat
for /f "delims=;" %%a in ("%strippedvar%") do echo %%a
set prestrippedvar=%strippedvar%
set strippedvar=%strippedvar:*;=%
if not "%prestrippedvar:;=%"=="%prestrippedvar%" goto :repeat

限制

  • 上述字符串处理不适用于参数变量(%1、%2 等)。

链接

命令行参数

[edit | edit source]

传递给批处理脚本的命令行参数,也称为命令行参数,可以通过 %1、%2、...、%9 访问。可能存在超过九个参数;要访问它们,请参阅下面如何循环遍历所有参数。

语法 %0 不引用命令行参数,而是引用批处理文件的名称。

测试是否已提供第一个命令行参数

if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b

使用 SHIFT 对所有命令行参数进行稳健循环(对于每个命令行参数,...)

:argactionstart
if -%1-==-- goto argactionend
echo %1 & REM Or do any other thing with the argument
shift
goto argactionstart
:argactionend

使用 SHIFT 对所有命令行参数进行稳健循环,而不修改 %1、%2 等。

call :argactionstart %*
echo Arg one: %1 & REM %1, %2, etc. are unmodified in this location
exit /b

:argactionstart
if -%1-==-- goto argactionend
echo %1 & REM Or do any other thing with the argument
shift
goto argactionstart
:argactionend
exit /b

将命令行参数传输到环境变量

setlocal EnableDelayedExpansion
REM Prevent affecting possible callers of the batch
REM Without delayed expansion, !arg%argno%! used below won't work.
set argcount=0
:argactionstart
if -%1-==-- goto argactionend
set /a argcount+=1
set arg%argcount%=%1
shift
goto argactionstart
:argactionend

set argno=0
:loopstart
set /a argno+=1
if %argno% gtr %argcount% goto loopend
echo !arg%argno%! & REM Or do any other thing with the argument
goto loopstart
:loopend

循环遍历所有命令行参数,虽然不是稳健的

for %%i in (%*) do (
  echo %%i
)

这看起来很优雅,但并不稳健,会错误处理包含通配符(*、?)的参数。特别是,上面的 for 命令用匹配它们的文件名替换包含通配符(*、?)的参数,或者如果没有任何文件匹配则删除它们。尽管如此,只要传递的参数不包含通配符,上面的循环就能按预期工作。

以非稳健的方式查找命令行参数的数量

set argcount=0
for %%i in (%*) do set /a argcount+=1

同样,这对于包含通配符的参数不起作用。

最大可能的参数数量大于 4000,如在 Windows Vista 机器上通过经验确定。该数量在 Windows XP 和 Windows 7 上可能会有所不同。

在将参数传递给批处理脚本时,用于参数分隔的字符是以下这些

  • 空格
  • 逗号
  • 分号
  • 等号
  • 制表符

因此,以下行传递了相同的四个参数

  • test.bat a b c d
  • test.bat a,b,c,d
  • test.bat a, b, c, d
  • test.bat a;b;c;d
  • test.bat a=b=c=d
  • test.bat a b,c;,;=d

是的,即使包含“a b,c;,;=d”的行也传递了四个参数,因为一系列分隔符被视为单个分隔符。

要在参数值中包含空格、逗号或分号,可以将值括在引号中。但是,引号将成为参数值的一部分。要在脚本中引用该参数时去掉包含的引号,可以使用 #百分号波浪号 中描述的 %~<number>。

在将参数传递给调用的命令而不是批处理脚本时,通常需要使用空格将命令与第一个参数分隔开。但是,对于内部命令,如果命令名称后的第一个字符是几个符号之一,包括 .\/ 等等,则不需要这种分隔。

  • echo.
    • 输出换行符。
  • tree.
    • 失败:未找到“tree.”。tree 是一个外部命令。
  • dir..
    • 列出父目录的内容。
  • cd..
    • 将当前目录更改为父目录。
  • cd\
    • 将当前目录更改为根目录。
  • start.
    • 从当前目录打开 Windows 资源管理器。
  • dir/b/s
    • 递归地列出目录内容,显示完整路径。

链接

通配符

[edit | edit source]

许多命令接受文件名通配符,这些字符不代表它们本身,并能够匹配一组文件名。

通配符

  • *(星号):任何字符序列
  • ?(问号):单个字符,除了句点(".")之外,或者如果它是文件名中最大无句点部分末尾一系列问号的一部分,则可能是零个字符;请参阅示例以了解说明

示例

  • dir *.txt
    • 匹配 Myfile.txt、Plan.txt 和任何其他扩展名为 .txt 的文件。
  • dir *txt
    • 不需要包含句点。但是,这也会匹配没有句点约定的文件名,例如 myfiletxt。
  • ren *.cxx *.cpp
    • 将所有扩展名为 .cxx 的文件重命名为扩展名为 .cpp 的文件。
  • dir a?b.txt
    • 匹配文件 aab.txt、abb.txt、a0b.txt 等。
    • 不匹配 ab.txt,因为问号后面跟着除问号或句点以外的字符不能匹配零个字符。
    • 不匹配 a.b.txt,因为问号不能匹配句点。
  • dir ???.txt
    • 匹配 .txt、a.txt、aa.txt 和 aaa.txt 等,因为序列中的每个问号后面跟着一个句点可以匹配任意数量的字符。
  • dir a???.b???.txt???
    • 匹配 a.b.txt 等。虽然最后一个问号序列后面没有句点,但它仍然是文件名中最大无句点部分末尾的序列。
  • dir ????????.txt & @REM 八个问号
    • 匹配与 *.txt 相同的文件,因为每个文件在 .txt 之前也都有一个不超过 8 个字符的短文件名。

短文件名的怪癖:通配符匹配同时在长文件名和通常隐藏的 8 个字符 + 句点 + 3 个字符的短文件名上执行。这可能会导致意外情况。

与其他一些操作系统的 shell 不同,cmd.exe shell 不会自行执行通配符扩展(用匹配模式的文件名列表替换包含通配符的模式)。每个程序都有责任将通配符视为通配符。这使得诸如“ren *.txt *.bat”之类的操作成为可能,因为 ren 命令实际上看到了 * 通配符而不是匹配通配符的文件列表。因此,“echo *.txt”不会显示当前文件夹中匹配模式的文件,而是直接输出“*.txt”。另一个结果是,您可以编写“findstr a.*txt”而不必担心“a.*txt”部分被当前文件夹中一些文件的名称替换。此外,递归的“findstr /s pattern *.txt”是可能的,而在其他一些操作系统中,“*.txt”部分将被当前文件夹中找到的文件名替换,忽略嵌套文件夹。

接受通配符的命令包括 ATTRIBCOPYDIRFINDSTRFORREN 等。

链接

用户输入

[edit | edit source]

您可以使用以下方法从用户获取输入

  • SET /P 命令
  • CHOICE 命令
  • 使用“type con >myfile.txt”,用户按下 Ctrl + Z 键可终止多行用户输入。

百分号波浪号

[edit | edit source]

命令行参数 包含文件名时,可以使用特殊语法获取有关文件的各种信息。

以下语法扩展到有关作为 %1 传递的文件的各种信息

语法 展开结果 示例
%~1 %1 不含引号 未提供
%~f1 带驱动器盘符的完整路径 C:\Windows\System32\notepad.exe
%~d1 驱动器盘符 C
%~p1 无驱动器盘符的路径,带尾部反斜杠 \Windows\System32\
%~n1 对于文件,则为不带路径和扩展名的文件名

对于文件夹,则为文件夹名称

notepad
%~x1 包括句点的文件名扩展名 .exe
%~s1 修改 f、n 和 x 以使用短名称 C:\PROGRA~2\WINDOW~3\ACCESS~1\wordpad.exe
%~a1 文件属性 --a------
%~t1 文件上次修改的日期和时间(格式取决于 Windows 的“区域设置”) 02.11.2006 11:45(例如,以“英语(美国)”格式)
%~z1 文件大小 151040
%~pn1 p 和 n 的组合 \Windows\System32\notepad
%~dpnx1 几个字母的组合 C:\Windows\System32\notepad.exe
%~$PATH:1 PATH 变量中存在的文件夹中找到的第一个匹配项的完整路径,或者在没有匹配项的情况下为空字符串。
%~n0 对 %0 应用 %~n

批处理的无扩展名名称

tildetest
%~nx0 对 %0 应用 %~nx

批处理的名称

tildetest.bat
%~d0 对 %0 应用 %~d

批处理的驱动器盘符

C
%~dp0 对 %0 应用 %~dp

批处理的文件夹,带尾部反斜杠

C:\Users\Joe Hoe\

相同的语法适用于由 FOR 命令创建的单字母变量,例如“%%i”。

要从命令行了解有关此主题的信息,请键入“call /?”或“for /?”。

链接

函数

[edit | edit source]

函数,也称为子程序,可以使用 CALL、标签、SETLOCALENDLOCAL 进行模拟。

确定算术幂的函数示例

@echo off
call :power 2 4
echo %result%
rem Prints 16, determined as 2 * 2 * 2 * 2
goto :eof

rem __Function power______________________
rem Arguments: %1 and %2
:power
setlocal
set counter=%2
set interim_product=%1
:power_loop
if %counter% gtr 1 (
  set /a interim_product=interim_product * %1
  set /a counter=counter - 1
  goto :power_loop
)
endlocal & set result=%interim_product%
goto :eof

虽然函数末尾的 goto :eof 实际上并不需要,但在一般情况下,如果有不止一个函数,则必须存在。

可以在调用行上指定应将结果存储在哪个变量中,如下所示

@echo off
call :sayhello result=world
echo %result%
exit /b

:sayhello
set %1=Hello %2
REM Set %1 to set the returning value
exit /b

在上面的示例中,exit /b 用于代替 goto :eof,它们的效果相同。

此外,请记住,等号是一种用于分隔参数的方法。因此,以下项实现相同的效果

  • call :sayhello result=world
  • call :sayhello result world
  • call :sayhello result,world
  • call :sayhello result;world

(请参阅 命令行参数 作为提醒)

链接

计算

[edit | edit source]

批处理脚本可以使用 SET /a 命令进行简单的 32 位带符号整数算术运算和按位操作。支持的最大整数为 2147483647 = 2 ^ 31 - 1。支持的最小整数为 -2147483648 = - (2 ^ 31),可以使用 set /a num=-2147483647-1 的技巧进行赋值。语法类似于 C 语言。

算术运算符包括 *、/、 %(取模)、+、-。在批处理中,取模必须输入为“%%”。没有求幂运算符。

按位运算符将数字解释为 32 个二进制位的序列。它们是 ~(补码)、&(与)、|(或)、^(异或)、<<(左移)、>>(算术,也称为符号保持右移)。没有逻辑,也称为符号清除右移,也没有位旋转运算符。

非运算符是  !: 它将零变为一,将非零变为零。

组合运算符是 ,: 它允许在一个 set 命令中进行更多计算。

组合赋值运算符以“+=”为模型,在“a+=b”中,它表示“a=a+b”。因此,“a-=b”表示“a=a-b”。类似地,*=、/=、 %=、&=、^=、|=、<<= 和 >>= 也是如此。

支持的运算符的优先级顺序如下

  1. ( )
  2. * / % + -
  3. << >>
  4. &
  5. ^
  6. |
  7. = *= /= %= += -= &= ^= |= <<= >>=
  8. ,

文字可以输入为十进制 (1234)、十六进制 (0xffff,以 0x 开头) 和八进制 (0777,以 0 开头)。

负整数的内部位表示形式为二进制补码。这为负整数提供按位操作、十六进制文字(大于 0x7FFFFFFF 且小于或等于 0xFFFFFFFF)的赋值和算术结果,以及算术运算的溢出和下溢行为。例如,-2147483648 表示为 0x80000000,因此二进制补码运算“set /a num=~(-2147483647-1)”得到 2147483647,等于 0x7FFFFFFF(键入 set /a num=0x7FFFFFFF 检查)。另一个例子,“-2 & 0xF”得到 14,因为 -2 是 0xFFFFFFFE,与 0xF 进行 AND 运算得到 0xE,即 14。虽然最大十进制文字是 2147483647,但最大十六进制文字是 0xFFFFFFFF,它被分配为十进制 -1。类似地,0xFFFFFFFE 被分配为十进制 -2,等等,因此,例如 0xFFFFFFFE - 2 得到 -4。大于 0xFFFFFFFF 的十六进制文字将转换为 -1,例如 0xFFFFFFFFFFFFFFFF,而大于 2147483647 的十进制文字会产生错误。最小的可表示的 32 位带符号整数是 -2147483648;“-2147483648”不能直接分配,因为这被解释为 -1 * 2147483648,而 2147483648 大于最大十进制文字 2147483647;但是,-2147483647-1 可以实现这一点,0x80000000 也可以。“-2147483647-2”下溢到最大的正整数 2147483647;类似地,“-2147483647-3”下溢到 2147483646。另一方面,“2147483647+1”溢出到 -2147483648,这对应于在内部位表示形式上执行加法,就好像它没有符号一样;“2147483647+2”溢出到 -2147483647,等等。

由于一些运算符对命令解释器有特殊含义,因此使用它们的表达式需要用引号括起来,例如

  • set /a num="255^127"
  • set /a "num=255^127"
    • 引号的替代放置。
  • set /a num=255^^127
    • 使用 ^ 而不是引号转义 ^。

示例

  • set /a n=(2+3)*5
    • 执行简单的计算并将结果存储在环境变量 n 中。当交互式调用(在批处理之外)时,输出计算结果,否则不输出任何内容。
  • set /a (2+3)*5
    • 当交互式调用(在批处理之外)时,输出计算结果,否则不输出任何内容。不更改任何变量,仅对交互式使用有用。
  • set n1=40 & set n2=25

    set /a n3=%n1%+%n2%

    • 使用标准百分号表示法进行变量扩展。
  • set n1=40 & set n2=25

    set /a n3=n1+n2

    • 避免在变量名称周围使用百分号表示法,因为 /a 无需使用。
  • set /a num="255^127"
    • 将 "^" 括在引号中,以防止它在命令解释器中具有特殊含义。
  • set /a n1 = (10 + 5)/5
    • 在 /a 中,= 周围的空格无关紧要。但是,习惯它有利于在没有 /a 的情况下编写 "set var = value",这将设置 "var " 而不是 "var" 的值。
  • if 1==1 (set /a n1=(2+4)*5)
    • 不起作用:分组括号内的算术括号会导致问题。
  • if 1==1 (set /a n1=^(2+4^)*5)
    • 使用插入符号 (^) 转义算术括号,或者将 "n1=2+(4*5)" 括在引号中,这两种方法都有效。
  • set /a n1=2+3,n2=4*7
    • 执行两个计算。
  • set /a n1=n2=2
    • 与 n1=2,n2=2 的效果相同。
  • set n1=40 & set n2=25 & set /a n3=n1+n2
    • 按预期工作。
  • set /a n1=2,n2=3,n3=n1+n2
    • 按预期工作。
  • set n1=40 & set n2=25 & set /a n3=%n1%+%n2%
    • 除非之前已设置 n1 和 n2,否则不起作用。变量规范 "%n1%" 和 "%n2"% 在第一个 set 命令执行 *之前* 被扩展。删除百分比符号使其正常工作。
  • set /a n1=2,n2=3,n3=%n1%+%n2%
    • 除非之前已设置 n1 和 n2,否则不起作用,原因与上一个示例中所述相同。
  • set /a n1=0xffff
    • 使用十六进制表示法设置 n1 为 "65535"。
  • set /a n1=0777
    • 使用八进制表示法设置 n1 为 "511"。
  • set /a n1=0xffffffff
    • 将 n1 设置为 -1。
  • set /a n1="~0"
    • 将 n1 设置为 -1,符合负整数的底层二进制补码表示。因此,非负整数的按位补码 (~) 会产生负整数。
  • set /a "n1=-1>>1"
    • 输出 -1,因为 ">>" 运算符是 *算术* 右移,保留了有符号 32 位整数底层位表示的最高位。请注意,-1 在内部是 0xFFFFFFFF。*逻辑* 右移(最高位丢弃)将导致 0x7FFFFFFF,即最大正 32 位整数。
  • set /a "n1=(-1>>1) & 0x7FFFFFFF"
    • 通过清除 32 位有符号整数底层位表示的最高位,模拟 *逻辑* 右移(最高位丢弃)1 位。
  • set /a "n=-1, shiftcount=4, n1=(n>>shiftcount) & (0x7FFFFFFF >> (shiftcount-1))"
    • 模拟 shiftcount > 0 的 *逻辑* 右移,当超过 1 位时需要清除多个最高位。
  • set /a "n1=1<<32"
    • 当右操作数为 32 或更高,或为负时,产生 0。这与现代 x86 处理器上左移指令的行为不同,该指令对 32 位寄存器右操作数进行掩码以将其限制为 5 位。因此,使用 x86 指令,结果将为 1,因为 32 & 0x1F 为 0。在 C 语言中,结果未定义,实际结果与平台相关。
  • set /a n1=%random%
    • 一个 0 到 32767 = 2^15-1 之间的伪随机数。
  • set /a n1=%random%>>10
    • 一个 0 到 31 = 2^5-1 之间的伪随机数。右移运算符丢弃了 15 位中的 10 位,保留了 5 位。
  • set /a n1=%random%%50
    • 一个 0 到 49 之间的伪随机数。使用 % 模运算符。在批处理中, %% 用于模运算:set /a n1=%random%%%50。由于模运算符的这种特定用法,结果并非完全均匀;如果第二个模运算符操作数(上面的 50)等于 2 的幂,例如 256 = 2^8,则结果是均匀的。
  • set /a n1="(%random%<<15)+%random%"
    • 一个 0 到 1073741823 = 2^30 - 1 之间的伪随机数。将 %random% 自身产生的两个 15 位随机数结合起来生成一个 30 位随机数。
  • set /a n1="((%random%<<15)+%random%)%1000000"
    • 如上所述,但再次使用模运算符,这次是为了实现 0 到 999999 的范围。

打印素数的示例计算

@echo off
setlocal
set n=1
:print_primes_loop
set /a n=n+1
set cand_divisor=1
:print_primes_loop2
set /a cand_divisor=cand_divisor+1
set /a cand_divisor_squared=cand_divisor*cand_divisor
if %cand_divisor_squared% gtr %n% echo Prime %n% & goto :print_primes_loop
set /a modulo=n%%cand_divisor
if %modulo% equ 0 goto :print_primes_loop & REM Not a prime
goto :print_primes_loop2

链接

查找文件

[edit | edit source]

可以使用 #DIR#FOR#FINDSTR#FORFILES#WHERE 查找文件。

示例

  • dir /b /s *base*.doc*
    • 输出当前文件夹及其子文件夹中的所有文件,文件名前缀包含单词 "base",扩展名以 "doc" 开头,包括 "doc" 和 "docx"。文件以完整路径输出,每行一个文件。
  • dir /b /s *.txt | findstr /i pers.*doc
    • 将输出文件(包括其完整路径)的结果与 findstr 过滤命令(支持有限的正则表达式)结合起来,为根据文件名和目录名查找文件提供了一种灵活且强大的组合。
  • for /r %i in (*) do @if %~zi geq 1000000 echo %~zi %i
    • 对于当前文件夹及其子文件夹中大小大于或等于 1,000,000 字节的每个文件,输出文件大小(以字节为单位)和文件的完整路径。有关 %~zi 中的语法,请参见 #Percent tilde
  • forfiles /s /d 06/10/2015 /c "cmd /c echo @fdate @path"
    • 对于当前文件夹及其子文件夹中在 2015 年 6 月 10 日或之后修改的每个文件,输出文件修改日期和完整文件路径。/d 后面的日期格式是特定于区域设置的。因此,允许查找最近修改的文件。
  • (for /r %i in (*) do @echo %~ti :: %i) | findstr 2015.*:
    • 递归搜索当前文件夹,输出最后修改日期为 2015 年的文件。在文件名之前放置修改日期和时间,后跟一个双冒号。只要使用的 Windows 版本和区域设置以包含四位数年份的格式显示日期,此方法就可以正常工作。双冒号用于确保 findstr 命令匹配的是日期而不是文件名。
  • for /r %i in (*) do @echo %~ti | findstr 2015 >NUL && echo %i
    • 如上所述,输出 2015 年更改的文件。与上面不同,只输出文件,不输出修改日期。
  • findstr /i /s /m cat.*mat *.txt
    • 根据文件内容查找文件。在以 .txt 结尾的文件中执行对正则表达式 cat.*mat 的全文搜索,并输出文件名。/m 开关确保只输出文件名。
  • where *.bat
    • 输出当前目录和 PATH 中目录中的所有 .bat 文件。

键盘快捷键

[edit | edit source]

在从标准控制台(在按下 Windows + R 后键入 cmd.exe 后出现)使用 Windows 命令行时,您可以使用多个键盘快捷键,包括功能键

  • Tab: 从当前文件夹中的文件名或文件夹名中完成相关部分的已键入字符串。相关部分通常是最后一个无空格部分,但使用引号会改变这一点。通常同时考虑文件和文件夹进行完成,但 cd 命令只考虑文件夹。
  • 上箭头键和下箭头键:一次输入一个命令历史记录中的命令。
  • Escape: 删除当前正在键入的命令行。
  • F1: 从命令历史记录中一次输入一个字符,输入之前输入的单个命令中的字符。每次后续按下 F1 都会输入一个字符。
  • F2: 要求您输入一个字符,并输入命令历史记录中之前命令的最短前缀,该前缀不包含已键入的字符。因此,如果之前的命令是 echo Hello world,并且您键入了 o,则会输入 ech。
  • F3: 输入命令历史记录中的单个之前命令。重复按下不会有任何其他效果。
  • F4: 要求您输入一个字符,并删除当前键入的字符串中从当前光标位置开始、向右继续并以您输入的字符(不包括该字符)结尾的部分。因此,如果您键入 echo Hello world,使用左箭头键将光标置于 H,按下 F4,然后按下 w,您将得到 echo world。如果您按下 F4,然后按下 Enter,将删除从光标到行尾的文本。
  • F5: 一次输入一个命令历史记录中的之前命令。
  • F6: 输入 Control+Z 字符。
  • F7: 打开一个带命令历史记录的基于字符的弹出窗口,并允许您使用箭头键和 Enter 选择一个命令。在弹出窗口中按下 Enter 后,命令将立即执行。
  • F8: 给定一个已键入的字符串,一次显示命令历史记录中以该字符串为前缀的项目。
  • F9: 允许您输入命令历史记录中命令的编号,然后执行该命令。
  • Alt + F7: 删除命令历史记录。

以上也被称为命令提示符键盘快捷键。

以上快捷键的可用性似乎不依赖于运行 DOSKEY

链接

路径

[edit | edit source]

文件和目录路径遵循某些约定。这些约定包括可能使用盘符后跟冒号 (:),使用反斜杠 (\) 作为路径分隔符,以及相对路径和绝对路径之间的区别。

正斜杠 (/) 在用作 (\) 的替代品时通常有效,但并非总是有效;它通常用于标记开关(选项)。使用正斜杠会导致各种模糊的行为,最好避免使用。

特殊设备名称包括 NUL、CON、PRN、AUX、COM1、...、COM9、LPT1、...、LPT9;这些可以重定向到。

示例

  • attrib C:\Windows\System32\notepad.exe
    • 如果文件存在,则会成功,因为它应该存在。这是一个包含盘符的 *绝对* 路径。它也被称为 *完全限定* 路径。
  • attrib \Windows\System32\notepad.exe
    • 如果当前驱动器为 C:,并且文件存在,则会成功,因为它应该存在。这是一个没有盘符的绝对路径。
  • cd /d C:\Windows & attrib System32\notepad.exe
    • 如果文件存在,则会成功。传递给 attrib 的路径是 *相对* 路径。
  • cd /d C:\Windows\System32 & attrib C:notepad.exe
    • 如果文件存在,则成功。传递给 attrib 的路径是相对路径,尽管包含驱动器盘符:必须存在 C:\notepad.exe,并且包含反斜杠才能使其成为绝对路径。
  • cd /d C:\Windows & attrib .\System32\notepad.exe
    • 如果文件存在,则成功。单个句点表示当前文件夹。
  • attrib .
    • 单个句点表示当前文件夹。
  • cd /d C:\Windows & attrib .\System32\\\notepad.exe
    • 如果文件存在,则成功。反斜杠的堆叠除了第一个反斜杠外没有其他影响。
  • cd /d C:\Windows & attrib .\System32
    • 如果文件夹存在,则成功。
  • cd /d C:\Windows & attrib .\System32\
    • 失败。通常情况下,文件夹不用最后的反斜杠表示。
  • cd C:\Windows\System32\
    • 成功,无论如何。
  • cd ..
    • 双句点表示父文件夹。
  • attrib C:\Windows\System32\..\..\Windows\System32
    • 双句点可以用于路径中间,用于导航到父文件夹,甚至可以多次使用。
  • attrib \\myserver\myvolume
    • 网络 UNC 路径以双反斜杠开头,没有驱动器盘符。
  • cd \\myserver\myvolume
    • 不工作;以这种直接的方式更改到服务器文件夹不起作用。
  • pushd \\myserver\folder
    • 自动为文件夹创建驱动器并更改到该驱动器。使用 #POPD 后,驱动器将再次取消分配。
  • attrib C:/Windows/System32/notepad.exe
    • 在多个版本的 cmd.exe 上成功。使用正斜杠。

链接

数组

[edit | edit source]

在延迟扩展模式下,可以使用 % 和 ! 的组合来模拟数组,以指示变量。其中,%i% 是变量 i 的值,使用立即扩展,而 !i! 是变量 i 的值,使用延迟扩展。

@echo off
setlocal EnableDelayedExpansion
for /l %%i in (1, 1, 10) do (
  set array_%%i=!random!
)

for /l %%i in (1, 1, 10) do (
  echo !array_%%i!
)

:: For each item in the array, not knowing the length
set i=1
:startloop
if not defined array_%i% goto endloop
set array_%i%=!array_%i%!_dummy_suffix
echo A%i%: !array_%i%!
set /a i+=1
goto startloop
:endloop

链接

Perl 单行命令

[edit | edit source]

一些任务可以使用 Perl 单行命令方便地实现。Perl 是一种脚本语言,起源于另一个操作系统的环境。由于许多 Windows 计算环境都安装了 Perl,因此 Perl 单行命令是 Windows 批处理脚本的自然且紧凑的扩展。

示例

  • echo "abcbbc"| perl -pe "s/a.*?c/ac/"
    • 让 Perl 充当 sed,该工具支持使用正则表达式指定的文本替换。
  • echo a b| perl -lane "print $F[1]"
    • 让 Perl 充当 cut 命令,显示该行的第 2 个字段或列,在本例中为 b。使用 $F[2] 显示第 3 个字段;索引从零开始。原生解决方案:FOR /f。
  • perl -ne "print if /\x22hello\x22/" file.txt
    • 充当 grep 或 FINDSTR,输出 file.txt 中与 if 后的正则表达式匹配的行。使用强大的 Perl 正则表达式,比 FINDSTR 的正则表达式更强大。
  • perl -ne "$. <= 10 and print" MyFile.txt
    • 让 Perl 充当 head -10 命令,输出文件的前 10 行。
  • perl -e "sleep 5"
    • 等待 5 秒。
  • for /f %i in ('perl -MPOSIX -le "print strftime '%Y-%m-%d', localtime"'') do @set isodate=%i
    • 将当前日期以 ISO 格式获取到 isodate 变量中。
  • perl -MWin32::Clipboard -e "print Win32::Clipboard->Get()"
    • 输出剪贴板的文本内容。存储到 getclip.bat 后,会产生一个方便的 getclip 命令来补充 CLIP 命令。
  • perl -MText::Diff -e "print diff 'File1.txt', 'File2.txt'"
    • 以类似于其他操作系统中 diff 命令的格式输出两个文件之间的差异,包括上下文行、以 + 开头的行和以 - 开头的行。
  • perl -MWin32::Sound -e "Win32::Sound::Play('C:\WINDOWS\Media\notify.wav');"
    • 播放 notify.wav 中的通知声音,不显示任何窗口。

在网络上,Perl 单行命令通常以另一个操作系统的命令行约定发布,包括使用撇号 (') 而不是 Windows 引号来包围参数。这些需要针对 Windows 进行调整。

链接

Unix 命令

[edit | edit source]

Windows cmd.exe 命令解释器可以使用类 Unix 操作系统的命令,前提是这些命令已安装。示例命令包括 grep、sed、awk、wc、head 和 tail。这些命令来自 GNU 项目,并且存在其 Windows 移植版本。您可以在 Unix 指南 Wikibook 中了解更多关于这些命令的信息。请注意,依赖这些命令的批处理程序不能保证在其他 Windows 机器上运行。

可以从以下项目获取免费许可的 Windows 版本的 GNU 命令

  • GnuWin32, sourceforge.net
  • ezwinports, sourceforge.net:具有一些比 GnuWin32 更新的移植版本

为 Windows 10 运行 GNU 命令的另一种方法是 Windows Subsystem for Linux。

更改文件时间戳

[edit | edit source]

没有其他操作系统中熟悉的 touch 命令。touch 命令将修改文件的最后修改时间戳,而不会改变其内容。

一个解决方法是,其可靠性和跨各种 Windows 版本的适用性尚不清楚,如下所示

  • copy /b file.txt+,,

链接

获取最后几行

[edit | edit source]

没有内置命令来获取文件的最后几行;没有 tail 命令的等效项。但是,可以编写一个批处理程序来完成这项工作,并且可以在下面的链接中找到。或者,可以为 Windows 安装 tail 命令,或者运行不需要安装的 PowerShell 等效命令。

链接

十六进制转储

[edit | edit source]

没有预安装的十六进制转储工具来以十六进制查看文件内容。尽管如此,还是有以下几种选择

1) 使用fsutil file createnew 创建一个全零字节文件,并使用fc 通过比较查看字节

  • fsutil file createnew allzeros.bin 1000
    fc /b C:\Windows\notepad.exe allzeros.bin
    • 在比较中没有显示 notepad.exe 中为零的字节,但其他字节及其偏移量(每行一个字节)将显示出来。您可以通过更改上面的最后一个 1000 来选择全零字节文件的长度,从而确定要查看多少个初始字节。要查看完整文件,请创建与要检查的文件长度相同长度的全零字节文件。这远非完美,但可以用作一个快速方法来查看例如 BOM 标记或使用的换行符类型。

2) 使用 certutil -encodeHex,其中 encodeHex 功能没有官方文档

  • certutil -encodeHex file.txt filehex.txt
    • 将 file.txt 的文件内容以十六进制写入 filehex.txt。如果 filehex.txt 存在,则拒绝覆盖它。您无法限制要转换的字节数。

3) 使用 PowerShell 5.0 Format-Hex

  • powershell Format-Hex C:\Windows\notepad.exe
    • 最新 PowerShell 支持选项 -Count。

4) 安装诸如功能丰富的odhexdump 之类的命令;请参见 Unix 命令od 也可以进行八进制转储。

5) 如果您使用的是旧的 32 位版 Windows(不太可能),请使用debug;请参见 DEBUG.

链接

以提升的权限运行

[编辑 | 编辑源代码]

如果您的用户具有提升的管理权限,您可以在以特定方式启动 cmd.exe 时使用这些权限。要以提升的权限启动 cmd.exe,您可以执行以下操作。

  • 选择“开始”菜单,并在其中键入“cmd.exe”。
  • 右键单击 cmd.exe 图标,然后选择“以管理员身份运行”。

要测试您是否拥有提升的权限

  • 运行“net session”,如果您没有权限,它将失败。

限制包括以下内容

  • 没有 while 循环;可以通过标签和 goto 模拟。有一个 for 循环和一个 if 语句。
  • 没有循环控制 break 和 continue 语句,这些语句来自 C 语言。
  • 没有合适的自定义函数;可以使用标签、调用和 %n 参数扩展创建自定义函数。
  • 对包含特殊字符(如引号 (") 或与号 (&))的字符串进行脆弱的处理。
  • 没有数组;可以以有限的方式模拟。
  • 没有关联数组,也称为字典。
  • 没有浮点运算。
  • 没有来自 C 语言的三元条件运算符。
  • 没有将字符转换为其 ASCII 值或将 ASCII 值转换为字符的函数。没有合理的变通方法。
  • 没有任意大的整数运算。
  • 没有 touch 命令可以更改来自其他操作系统的文件时间戳;没有 head 和 tail 命令。
  • 没有 GUI 编程。
  • 还有更多。

内置命令

[编辑 | 编辑源代码]

这些命令都内置在命令解释器本身中,无法更改。有时这是因为它们需要访问内部命令解释器数据结构,或修改命令解释器进程本身的属性。

命令 描述
ASSOC 将扩展名与文件类型 (FTYPE) 关联。
BREAK 设置或清除扩展的 CTRL+C 检查。
CALL 从另一个批处理程序中调用一个批处理程序。
CDCHDIR 输出或设置当前目录。
CHCP 输出或设置活动代码页号。
CLS 清除屏幕。
COLOR 设置控制台的前景色和背景色。
COPY 复制文件。
DATE 输出并设置系统日期。
DELERASE 删除一个或多个文件。
DIR 输出目录中文件和子目录的列表。
ECHO 输出消息,或打开或关闭命令回显。
ELSE 当 "IF" 不为真时,在批处理程序中执行条件处理。
ENDLOCAL 结束批处理文件中环境更改的本地化。
EXIT 退出 CMD.EXE 程序(命令解释器)。
FOR 对一组文件中的每个文件运行指定的命令。
FTYPE 设置文件类型命令。
GOTO 跳转到标签。
IF 在批处理程序中执行条件处理。
MDMKDIR 创建目录。
MOVE 将文件移动到新位置
PATH 设置或修改 PATH 环境
PAUSE 使命令会话暂停以等待用户输入。
POPD 更改为从目录堆栈中弹出的驱动器和目录
PROMPT 设置或修改等待输入时显示的字符串。
PUSHD 将当前目录压入堆栈,并更改为新目录。
RD / RMDIR 删除目录。
REM 注释命令。与双冒号 (::) 不同,可以执行该命令。
REN / RENAME 重命名文件或目录。
SET 设置或输出 shell 环境变量。
SETLOCAL 为批处理文件创建子环境。
SHIFT 将批处理参数向前移动。
START 使用各种选项启动程序。
TIME 输出或设置系统时钟。
TITLE 更改窗口标题
TYPE 将文件的内容打印到控制台。
VER 显示命令处理器、操作系统版本。
VERIFY 验证文件复制是否已正确完成。
VOL 显示当前卷的标签。

将扩展名与文件类型 (FTYPE) 关联,输出现有关联,或删除关联。另请参见 FTYPE

示例

  • assoc
    • 列出所有关联,格式为“<文件扩展名>=<文件类型>”,例如“.pl=Perl”或“.xls=Excel.Sheet.8”。
  • assoc | find ".doc"
    • 列出所有包含“.doc”子字符串的关联。

链接

在基于 Windows NT 的 Windows 版本中,不执行任何操作;出于与 MS DOS 的兼容性而保留。

示例

  • break > empty.txt
    • 创建空文件或清除现有文件的內容,利用 break 不执行任何操作且没有输出这一事实。比 "type nul > empty.txt" 更短。

链接

从另一个批处理程序中调用一个批处理程序,在一个批处理程序中调用一个子程序,或者,作为一项未公开的行为,启动一个程序。特别地,暂停调用者的执行,开始执行被调用者,并在被调用者完成执行时,如果需要,恢复调用者的执行。

有关调用子程序的信息,请参见 函数 部分。

请注意,在不使用 call 关键字的情况下,从批处理中调用批处理会导致执行永远不会返回到调用者,因为被调用者已完成。

被调用者继承调用者的环境变量,并且除非被调用者通过 SETLOCAL 阻止这种情况,否则被调用者对环境变量所做的更改将在调用者恢复执行后对调用者可见。

示例

  • mybatch.bat
    • 如果在批处理中使用,则将控制权转移到 mybatch.bat,并且永远不会恢复调用者的执行。
  • call mybatch.bat
  • call mybatch
  • call mybatch.bat arg1 "arg 2"
  • call :mylabel
  • call :mylabel arg1 "arg 2"
  • cmd /c mybatch.bat
    • 类似于 call,但即使出现错误也会恢复执行。此外,被调用者对环境变量所做的任何更改都不会传播到调用者。
  • call notepad.exe
    • 启动记事本,或者一般而言,启动任何其他可执行文件。这显然不是 call 的预期用法,并且没有正式记录。

另请参见 函数CMDSTART

链接

更改为不同的目录,或输出当前目录。但是,如果使用了不同的驱动器号,则不会切换到该不同的驱动器或卷。

示例

  • cd
    • 输出当前目录,例如 C:\Windows\System32。
  • cd C:\Program Files
    • 路径中有空格时,不需要周围的引号。
  • cd \Program Files
  • cd Documents
  • cd %USERPROFILE%
  • cd /d C:\Program Files
    • 更改为 C: 驱动器的目录,即使 C: 不是当前驱动器。
  • C: & cd C:\Program Files.
    • 更改为 C: 驱动器的目录,即使 C: 不是当前驱动器。
  • cd ..
    • 更改为上级目录。如果已经在根目录中,则不执行任何操作。
  • cd ..\..
    • 更改为向上两级的上级目录。
  • C: & cd C:\Windows\System32 & cd ..\..\Program Files
    • 使用 ".." 在目录树中上下导航
  • cd \\myserver\folder
    • 不起作用。无法直接将目录更改为网络通用命名约定 (UNC) 文件夹。关键词:UNC 路径。
  • subst A: \\myserver\folder && cd /d A
    • 使用 #SUBST 命令将目录更改为服务器文件夹,假设驱动器号 A: 可用。
  • pushd \\myserver\folder
    • 自动为文件夹创建驱动器并更改到该驱动器。使用 #POPD 后,驱动器将再次取消分配。
  • cd C:\W*
    • 更改为 C:\Windows,在典型的 Windows 设置中。因此,通配符有效。这对于从命令行手动键入很有用。
  • cd C:\W*\*32
    • 更改为 C:\Windows\System32,在典型的 Windows 设置中。

链接

CD 的同义词。

清除屏幕。

设置控制台的前景色和背景色。

示例

  • color f9
    • 使用白色背景和蓝色前景色。
  • color
    • 恢复原始颜色设置。

链接

复制文件。另请参见MOVEXCOPYROBOCOPY

示例

  • copy F:\File.txt
    • 将文件复制到当前目录,假设当前目录不是 F:\。
  • copy "F:\My File.txt"
    • 与上面相同;需要使用引号将包含空格的文件包围。
  • copy F:\*.txt
    • 将位于 F:\ 并以 .txt 结尾的文件复制到当前目录,假设当前目录不是 F:\。
  • copy F:\*.txt .
    • 与上面的命令相同。
  • copy File.txt
    • 显示错误消息,因为无法将 File.txt 复制到自身。
  • copy File1.txt File2.txt
    • 将 File1.txt 复制到 File2.txt,如果用户确认或从批处理脚本运行,则覆盖 File2.txt。
  • copy File.txt "My Directory"
    • 将 File.txt 复制到 "My Directory" 目录,假设 "My Directory" 存在。
  • copy Dir1 Dir2
    • 将直接位于目录 Dir1 中的所有文件复制到 Dir2,假设 Dir1 和 Dir2 是目录。不会复制位于 Dir1 的嵌套目录中的文件。
  • copy *.txt *.bak
    • 对于当前文件夹中的每个 *.txt 文件,创建一个以 "bak" 结尾而不是 "txt" 结尾的副本。

链接

删除文件。谨慎使用,尤其是在与通配符结合使用时。仅删除文件,不删除目录,请参见RD。有关更多信息,请键入 "del /?"。

示例

  • del File.txt
  • del /s *.txt
    • 递归删除文件,包括嵌套目录,但保留目录;不加询问地删除所有匹配的文件。
  • del /p /s *.txt
    • 与上面相同,但在删除每个文件之前都会询问确认。
  • del /q *.txt
    • 不询问确认就删除。

链接

列出目录的内容。提供各种选项。键入 "dir /?" 以获取更多帮助。

示例

  • dir
    • 列出当前文件夹中的文件和文件夹,不包括隐藏文件和系统文件;如果 DIRCMD 变量不为空且包含 dir 的开关,则使用不同的列出方式。
  • dir D
  • dir /b C:\Users
  • dir /s
    • 递归列出目录及其所有子目录的内容。
  • dir /s /b
    • 递归列出目录及其所有子目录的内容,每行一个文件,显示每个列出文件或目录的完整路径。
  • dir *.txt
    • 列出所有扩展名为 .txt 的文件。
  • dir /a
    • 在列表中包含隐藏文件和系统文件。
  • dir /ah
    • 仅列出隐藏文件。
  • dir /ad
    • 仅列出目录。/A 后的其他字母包括 S、I、R、A 和 L。
  • dir /ahd
    • 仅列出隐藏目录。
  • dir /a-d
    • 仅列出文件,不包括目录。
  • dir /a-d-h
    • 仅列出非隐藏文件,不包括目录。
  • dir /od
    • 按上次修改日期对文件和文件夹进行排序。/O 后的其他字母包括 N(按名称)、E(按扩展名)、S(按大小)和 G(文件夹优先)
  • dir /o-s
    • 按大小降序对文件进行排序;对文件夹排序的影响尚不清楚。
  • dir /-c /o-s /a-d
    • 按大小降序列出文件,通过 /-C 省略千位分隔符,不包括文件夹。
  • dir /s /b /od
    • 递归列出目录及其所有子目录的内容,按每个目录的上次修改日期对文件进行排序。排序仅在每个目录中进行;不会对找到的所有文件的完整集合进行排序。
  • dir /a /s
    • 递归列出文件,包括隐藏文件和系统文件。通过考虑输出的最后几行,可用于找出磁盘使用情况(目录大小)。

链接

输出或设置日期。日期的输出方式取决于国家/地区设置。也可以使用 "echo %DATE%" 输出日期。

以 ISO 格式获取日期,如 "2000-01-28":这并不容易,因为日期格式取决于国家/地区设置。

  • 如果您假设格式为 "Mon 01/28/2000",则以下操作将起作用
    • set isodate=%date:~10,4%-%date:~4,2%-%date:~7,2%
  • 如果您有WMIC,则以下操作与区域设置无关
    • for /f %i in ('wmic os get LocalDateTime') do @if %i lss a if %i gtr 0 set localdt=%i
      set isodate=%localdt:~0,4%-%localdt:~4,2%-%localdt:~6,2%
    • 要在批处理中使用上述代码,请将 %i 更改为 %%i 并从 if 之前的 @ 中删除。
  • 如果您安装了 Perl
    • for /f %i in ('perl -MPOSIX -le "print strftime '%Y-%m-%d', localtime"'') do @set isodate=%i

链接

输出消息,或打开或关闭命令回显。

示例

  • echo on
  • @echo off
  • echo Hello
  • echo "hello"
    • 也输出引号。
  • echo %PATH%
    • 输出 PATH 变量的内容。
  • echo Owner ^& son
    • 使用脱字符 (^) 转义与符号 (&),从而能够回显与符号。
  • echo 1&echo 2&echo 3
    • 输出三个字符串,每个字符串后跟一个换行符。
  • echo.
    • 输出一个换行符,而句点没有被输出。如果没有句点,则输出 "echo off" 或 "echo on"。在句点前添加空格会导致句点被输出。其他具有与句点相同效果的字符包括 :;,/\(=+[].
  • echo %random%>>MyRandomNumbers.txt
    • 虽然它看起来像是在向 MyRandomNumbers.txt 输出随机数,但实际上它不会为 0-9 的数字这样做,因为这些数字放在 >> 前面时表示要重定向的通道。另请参见#重定向
  • echo 2>>MyRandomNumbers.txt
    • 将标准错误重定向到文件,而不是回显 2。
  • (echo 2)>>MyRandomNumbers.txt
    • 即使是较小的数字(在本例中为 2)也回显并重定向结果。
  • >>MyRandomNumbers.txt echo 2
    • 另一种回显即使是较小的数字并重定向结果的方式。

显示不带换行符的字符串需要使用技巧

  • set <NUL /p=Output of a command
    • 输出 "Output of a command:"。下一条命令的输出将立即显示在 ":" 后面。
  • set <NUL /p=Current time: & time /t
    • 输出 "Current time: " 后跟 "time /t" 的输出。
  • (set <NUL /p=Current time: & time /t) >tmp.txt
    • 与之前相同,将两条命令的输出重定向到文件。

链接

一个例子

if exist file.txt (
  echo The file exists.
) else (
  echo The file does not exist.
)

另请参见IF

结束使用SETLOCAL 开始的本地环境变量集。可用于创建子程序:请参见函数

链接

DEL 的同义词。

退出 DOS 控制台,或者使用 /b 仅退出当前正在运行的批处理或当前正在执行的子例程。如果在批处理文件中不使用 /b,则会导致调用批处理的 DOS 控制台关闭。

示例

  • exit
  • exit /b

链接

迭代一系列值,执行命令。关键字:循环。

在以下示例中,%i 用于命令行,而 %%i 用于批处理。索引(例如 %i)必须是一个单字符变量名。

不带开关和带 /r 和 /d 开关的示例

  • for %%i in (1,2,3) do echo %%i
    • 在批处理中,回显 1、2 和 3。在批处理中,命令必须使用双百分号。
    • 其余示例旨在直接粘贴到命令行中,因此它们使用单百分号并包含 "@" 以防止重复显示。
  • for %i in (1,2,3) do @echo %i
    • 从命令行回显 1、2 和 3。
    • for 命令尝试将项目解释为文件名以及包含通配符的文件名模式。
    • 即使项目不匹配现有文件名,它也不会报错。
  • for %i in (1,2,a*d*c*e*t) do @echo %i
    • 除非您碰巧有一个匹配第三个模式的文件,否则回显 1 和 2,放弃第三个项目。
  • for %i in (1 2,3;4) do @echo %i
    • 回显 1、2、3 和 4。是的,使用的是项目分隔符的混合。
  • for %i in (*.txt) do @echo %i
    • 回显位于当前文件夹中且扩展名为 .txt 的文件的文件名。
  • for %i in ("C:\Windows\system32\*.exe") do @echo %i
    • 回显匹配该模式的文件名。
  • for /r %i in (*.txt) do @echo %i
    • 回显当前文件夹(包括子文件夹)中所有扩展名为 .txt 的文件的完整路径和文件名。
  • for /d %i in (*) do @echo %i
    • 回显当前文件夹中所有文件夹的名称。
  • for /r /d %i in (*) do @echo %i
    • 回显当前文件夹(包括子文件夹)中所有文件夹的完整路径和名称。
  • for /r %i in (*) do @if %~zi geq 1000000 echo %~zi %i
    • 对于当前文件夹及其子文件夹中大小大于或等于 1,000,000 字节的每个文件,输出文件大小(以字节为单位)和文件的完整路径。有关 %~zi 中的语法,请参见 #Percent tilde

/l 开关示例

  • for /l %i in (1,2,11) do @echo %i
    • 回显从 1 到 11 的数字,步长为 2。格式为 (起始值,步长,结束值)。支持 32 位有符号整数。
  • for /l %i in (10,-1,1) do @echo %i
    • 回显从 10 到 1 的数字,递减。
  • for /l %i in (1,0,1) do @echo %i
    • 持续回显 1;无限循环。
  • for /l %i in (0) do @echo %i
    • 持续回显 0;无限循环。
  • for /l %i in () do @echo %i
    • 持续回显 0;无限循环。
  • for /l %i in (-10,1) do @echo %i
    • 回显从 -10 到 0 的数字;未明确指定的结束值默认为零。
  • for /l %i in (0xF, 1, 020) do @echo %i
    • 回显从 15 到 16 的数字;因此,支持十六进制和八进制字面量。
  • for /l %i in (2147483646,1,2147483647) do @echo %i
    • 回显 2147483646,然后是 2147483647,然后是 -2147483648,然后是 -2147483647,等等。这可能是由于 2147483647 的增量溢出到 -2147483648 造成的。
  • for /l %i in (-2147483648,1,-2147483647) do @echo %i
    • 回显 -2147483648 和 -2147483647。因此,直接支持 -2147483648 字面量,与 set /a 不同。

/f 开关示例

  • for /f "tokens=*" %i in (list.txt) do @echo %i
    • 对文件中的每一行,回显该行。
  • for /f "tokens=*" %i in (list1.txt list2.txt) do @echo %i
    • 对文件中的每一行,回显该行。
  • for /f "tokens=*" %i in (*.txt) do @echo %i
    • 不执行任何操作。不接受匹配文件名的通配符。
  • for /f "tokens=1-3 delims=:" %a in ("First:Second::Third") do @echo %c-%b-%a
    • 将字符串解析成以 “:” 为分隔符的标记。
    • 引号表示字符串不是文件名。
    • 即使在 "do" 之前的命令部分没有明确提及 %b 和 %c,但第二个和第三个标记存储在 %b 和 %c 中。
    • 两个连续的冒号被视为一个分隔符;%c 不是 "",而是 "Third"。
    • 执行其他操作系统中 cut 命令的部分功能。
  • for /f "tokens=1-3* delims=:" %a in ("First:Second::Third:Fourth:Fifth") do @echo %c-%b-%a: %d
    • 与上面相同,只是第四个和第五个项目被捕获到 %d 中,作为 "Fourth:Fifth",包括分隔符。
  • for /f "tokens=1-3* delims=:," %a in ("First,Second,:Third:Fourth:Fifth") do @echo %c-%b-%a: %d
    • 可以有多个分隔符。
  • for /f "tokens=1-3" %a in ("First Second Third,item") do @echo %c-%b-%a
    • 默认分隔符是空格和制表符。因此,它们与传递给批处理的以分隔符分隔的参数不同。
  • for /f "tokens=*" %i in ('cd') do @echo %i
    • 对命令结果的每一行,回显该行。
  • for /f "tokens=*" %i in ('dir /b /a-d-h') do @echo %~nxai
    • 对当前文件夹中的每个非隐藏文件,输出文件属性,后跟文件名。在字符串 "%~nxai" 中,使用 #Percent tilde 中描述的语法。
  • for /f "usebackq tokens=*" %i in (`dir /b /a-d-h`) do @echo %~nxai
    • 与上面相同,但使用反引号 (`) 将要执行的命令括起来。
  • for /f "tokens=*" %i in ('tasklist ^| sort ^& echo End') do @echo %i
    • 要执行的命令中的管道和与运算符必须使用插入符号 (^) 转义。

重定向示例

  • (for %i in (1,2,3) do @echo %i) > anyoldtemp.txt
    • 要重定向整个 for 循环的结果,请将整个循环放在方括号内,然后重定向。否则,重定向将绑定到循环主体,因此循环主体的每次新迭代都会覆盖之前迭代的结果。
  • for %i in (1,2,3) do @echo %i > anyoldtemp.txt
    • 与上面相关的示例。它显示了未将循环放在方括号内的后果。

继续: 要跳转到循环的下一轮迭代,从而模拟许多语言中已知的 continue 语句,可以使用 goto,前提是将循环主体放在子例程中,如下所示

for %%i in (a b c) do call :for_body %%i
exit /b

:for_body
    echo 1 %1
    goto :cont
    echo 2 %1
  :cont
exit /b

如果您直接在 for 循环中使用 goto,goto 的使用将破坏循环簿记。以下操作失败

for %%i in (a b c) do (
    echo 1 %%i
    goto :cont
    echo 2 %%i
  :cont
    echo 3 %%i
)

链接

FTYPE

[edit | edit source]

输出或设置要为文件类型执行的命令。另请参阅 ASSOC

示例

  • ftype
    • 列出所有与文件类型关联的要执行的命令,例如,'Perl="C:\Perl\bin\perl.exe" "%1" %*'
  • ftype | find "Excel.Sheet"
    • 仅列出显示行中包含 "Excel.Sheet" 的关联。

链接

跳转到标签。

一个例子

goto :mylabel
echo Hello 1
REM Hello 1 never gets printed.

:mylabel
echo Hello 2
goto :eof

echo Hello 3
REM Hello 3 never gets printed. Eof is a virtual label standing for the end of file.

在 for 循环的主体内使用 goto 会使 cmd 忘记循环,即使标签在同一个循环主体中也是如此。

链接

有条件地执行命令。在 CMD 提示符下输入 IF /? 可查看文档。

可用的基本测试

  • exist <filename>
  • <string>==<string>
  • <expression1> equ <expression2> -- 等于
  • <expression1> neq <expression2> -- 不等于
  • <expression1> lss <expression2> -- 小于
  • <expression1> leq <expression2> -- 小于或等于
  • <expression1> gtr <expression2> -- 大于
  • <expression1> geq <expression2> -- 大于或等于
  • defined <variable>
  • errorlevel <number>
  • cmdextversion <number>

可以对每个基本测试应用 "not"。显然,没有像 AND、OR 等运算符来组合基本测试。

/I 开关使 == 和 equ 比较忽略大小写。

一个例子

if not exist %targetpath% (
  echo Target path not found.
  exit /b
)

示例

  • if not 1 equ 0 echo Not equal
  • if 1 equ 0 echo A & echo B
    • 不执行任何操作;两个 echo 命令都受条件约束。
  • if not 1 equ 0 goto :mylabel
  • if not a geq b echo Not greater
  • if b geq a echo Greater
  • if b geq A echo Greater in a case-insensitive comparison
  • if B geq a echo Greater in a case-insensitive comparison
  • if 0 equ 00 echo Numerical equality
  • if not 0==00 echo String inequality
  • if 01 geq 1 echo Numerical comparison
  • if not "01" geq "1" echo String comparison
  • if 1 equ 0 (echo Equal) else echo Unequal
    • 请注意,正 then 部分周围的方括号使其生效。
  • if not a==A echo Case-sensitive inequality
  • if /i a==A echo Case-insensitive equality
  • if /i==/i echo This does not work
  • if "/i"=="/i" echo Equal, using quotation marks to prevent the literal meaning of /i

链接

创建新目录或目录。有一个同义词 MKDIR;另请参阅其反义词 RD

示例

  • md Dir
    • 在当前目录中创建一个目录。
  • md Dir1 Dir2
    • 在当前目录中创建两个目录。
  • md "My Dir With Spaces"
    • 在当前目录中创建名称包含空格的目录。

链接

MKDIR

[edit | edit source]

MD 的同义词。

[edit | edit source]

创建符号链接或其他类型的链接。从 Windows Vista 开始可用。

链接

在目录之间移动文件或目录,或重命名它们。另请参阅 REN

示例

  • move File1.txt File2.txt
    • 将 File1.txt 重命名为 File2.txt,如果用户确认或从批处理脚本运行,则覆盖 File2.txt。
  • move File.txt Dir
    • 将 File.txt 文件移入 Dir 目录,假设 File.txt 是一个文件,而 Dir 是一个目录;如果满足覆盖条件,则覆盖目标文件 Dir\a.txt。
  • move Dir1 Dir2
    • 将目录 Dir1 重命名为 Dir2,假设 Dir1 是一个目录,而 Dir2 不存在。
  • move Dir1 Dir2
    • 将目录 Dir1 移入 Dir2,导致 Dir2\Dir1 存在,假设 Dir1 和 Dir2 都是现有目录。
  • move F:\File.txt
    • 将文件移入当前目录。
  • move F:\*.txt
    • 将位于 F:\ 且以点 txt 结尾的文件移入当前目录,假设当前目录不是 F:\。

链接

输出或设置 PATH 环境变量的值。输出时,在输出开头包含 "PATH="。

示例

  • path
    • 输出 PATH。示例输出
      • PATH=C:\Windows\system32;C:\Windows;C:\Program Files\Python27
  • path C:\Users\Joe Hoe\Scripts;%path%
    • 将 PATH 扩展为 C:\Users\Joe Hoe\Scripts,仅适用于 cmd.exe 的进程。
  • path ;
    • 清空 PATH。
  • echo %path% | perl -pe "s/;/\n/g" | sort
    • 如果您安装了 perl,则显示 PATH 中的文件夹,按排序顺序。

链接

PAUSE

[edit | edit source]

提示用户并等待输入一行。

链接

从目录堆栈中弹出的驱动器和目录的更改。目录堆栈使用 PUSHD 命令填充。

链接

可用于更改或重置 cmd.exe 提示符。它设置 PROMPT 环境变量的值。

C:\>PROMPT MyPrompt$G

MyPrompt>CD
C:\

MyPrompt>PROMPT

C:\>

PROMPT 命令用于将提示符设置为“MyPrompt>”。CD 显示当前目录路径为“C:\”。在没有参数的情况下使用 PROMPT 会将提示符恢复到目录路径。

链接

将当前目录推送到目录堆栈中,使其可供 POPD 命令检索,并且如果使用参数执行,则更改到作为参数声明的目录。

链接

删除目录。另见其同义词 RMDIR 和反义词 MD。默认情况下,只能删除空目录。还可以输入“rd /?”。

示例

  • rd Dir1
  • rd Dir1 Dir2
  • rd "My Dir With Spaces"
  • rd /s Dir1
    • 删除目录 Dir1,包括其中的所有文件和子目录,在继续删除之前询问一次确认。要递归地删除嵌套目录中的文件,并对每个文件进行确认,请使用带有 /s 开关的 DEL
  • rd /q /s Dir1
    • 如上所述,但不询问确认。

链接

重命名文件和目录。

示例

  • ren filewithtpyo.txt filewithtypo.txt
  • ren *.cxx *.cpp

链接

这是 REN 命令的同义词。

用于批处理文件中的备注,防止执行备注的内容。

一个例子

REM A remark that does not get executed
echo Hello REM This remark gets displayed by echo
echo Hello & REM This remark gets ignored as wished
:: This sentence has been marked as a remark using double colon.

REM 通常放在行首。如果放在命令后面,它不起作用,除非前面带有与号,如上面的示例所示。

双冒号是 REM 的替代方法。在括号中的序列中间使用它时会导致问题,例如在 FOR 循环中使用的那些。双冒号似乎只是一个技巧,一个以冒号开头的标签。

链接

这是 RD 的同义词。

输出或设置环境变量。使用 /P 开关,它会向用户询问输入,并将结果存储在变量中。使用 /A 开关,它会执行简单的算术运算,并将结果存储在变量中。在字符串赋值中,通常会避免等号前后有空格,因为它们会导致通常意想不到的后果:“set name = Peter”将赋值给变量“name ”,而“set name=Peter”将赋值给变量“name”。另见 #环境变量#计算

示例

  • set
    • 以 VAR=VALUE 的格式输出环境变量及其值列表,每行一个变量。
  • set home
    • 以 VAR=VALUE 的格式输出以“home”开头的变量名称的环境变量及其值列表,不区分大小写,每行一个变量。
  • set HOME
    • 如上所述;变量名称前缀与变量名称之间的匹配不区分大小写。
  • set myname=Joe Hoe
    • 将变量设置为新值。
  • set mynumber=56
    • 将变量设置为字符串值“56”。
  • set mynumber=
    • 取消设置变量,将其从变量中删除。等号(=)必须是最后一个字符;在等号后面有任何空格,它们将成为变量的新值。
  • set home=%home%;C:\Program Files\My Bin Folder
  • set /P user_input=Enter an integer
  • set /P firstline=< File.txt
    • 将变量设置为文件的第一行。等效于其他操作系统的 head -1 命令。
  • set /A result = 4 * ( 6 / 3 )
    • 使用计算结果设置结果变量。另见 #计算
  • set name = Peter
    echo *%name %*
    • 将变量“name ”的值(结尾有空格)设置为“ Peter”(开头有空格)的值。意图可能是使用“set name=Peter”,没有分隔空格。

链接

在批处理文件中使用时,使对环境变量的所有后续更改都对当前批处理文件局部生效。在批处理文件外部使用时,不执行任何操作。可以使用 ENDLOCAL 结束。退出批处理文件会自动调用“end local”。可用于创建子程序:见 函数

此外,可以用来启用延迟扩展,如下所示:“setlocal EnableDelayedExpansion”。延迟扩展是指,只有在执行到达其使用位置后,才用其值替换用感叹号括起来的变量名,而不是在更早的时间点替换。

以下是一个在脚本中使用延迟扩展的示例,该脚本打印文件的指定数量的第一行,提供其他操作系统中已知的“head”命令的一些功能

@echo off

call :myhead 2 File.txt
exit /b

:: Function myhead
:: ===============
:: %1 - lines count, %2 - file name
:myhead
setlocal EnableDelayedExpansion
set counter=1
for /f "tokens=*" %%i in (%2) do ( 
  echo %%i
  set /a counter=!counter!+1
  if !counter! gtr %1 exit /b
)
exit /b

链接

将批处理文件参数沿着一并移动,但不影响 %*。因此,如果 %1=Hello 1,%2=Hello 2,%3=Hello 3,则在 SHIFT 后,%1=Hello 2,%2=Hello 3,但 %* 为“Hello 1” “Hello 2” “Hello 3”。

链接

在新窗口中启动程序,或打开文档。使用不清楚的算法来确定第一个传递的参数是窗口标题还是要执行的程序;假设:它使用第一个参数周围是否有引号作为提示,表示它是窗口标题。

示例

  • start notepad.exe & echo "Done."
    • 启动 notepad.exe,在不等待启动的程序完成的情况下继续执行下一条命令。关键字:异步。
  • start "notepad.exe"
    • 启动一个新的控制台窗口,其标题为 notepad.exe,这显然是不可取的结果。
  • start "" "C:\Program Files\Internet Explorer\iexplore.exe"
    • 启动 Internet Explorer。作为第一个参数传递的空 "" 是实际上没有打开的控制台的窗口标题,或者至少不是可见的。
  • start "C:\Program Files\Internet Explorer\iexplore.exe"
    • 启动一个新的控制台窗口,其标题为“C:\Program Files\Internet Explorer\iexplore.exe”,这显然是不可取的结果。
  • start /wait notepad.exe & echo "Done."
    • 启动 notepad.exe,等待它结束再继续执行。
  • start /low notepad.exe & echo "Done."
    • 如上所述,但以低优先级启动程序。
  • start "" MyFile.xls
    • 在分配用来打开该文档的程序中打开文档。
  • start
    • 在同一个当前文件夹中启动一个新的控制台(命令行窗口)。
  • start .
    • 在 Windows 资源管理器中打开当前文件夹。
  • start ..
    • 在 Windows 资源管理器中打开父文件夹。
  • start "" "mailto:"
    • 启动用于编写新电子邮件的应用程序。
  • start "" "mailto:[email protected]?subject=Notification&body=Hello Joe, I'd like to..."
    • 启动用于编写新电子邮件的应用程序,指定新电子邮件的收件人、主题和正文。
  • start "" "mailto:[email protected]?subject=Notification&body=Hello Joe,%0a%0aI'd like to..."
    • 如上所述,使用 %0a 输入换行符。
  • start /b TODO:example-application-where-this-is-useful
    • 启动应用程序,但不打开新的控制台窗口,将输出重定向到调用 start 命令的控制台。

链接

输出或设置系统时间。另请参见#DATE#Special variable names中的TIME变量。

示例

  • time /t
    • 以HH:MM格式输出系统时间,不包括秒和毫秒。例如:09:19。
  • time
    • 以特定于区域设置的格式输出系统时间,可能包含秒和百分之一秒,并提示设置新的时间;时间前面会显示特定于区域设置的消息,通常是“当前时间:”的翻译。因此,输出格式与“time /t”不同。
  • echo %time%
    • 使用特殊变量TIME以特定于区域设置的格式输出当前时间,包含小时、分钟、秒,以及可能包含的百分之一秒。某个区域设置的示例输出:9:19:31.55。
  • echo %time% & timeout 1 >nul & echo,|time
    • 输出中间命令(此处为timeout 1)前后时间。可用于测量中间序列的执行时间;关键词:需要多长时间。

链接

TITLE

[edit | edit source]

设置在控制台窗口中显示的标题。

链接

将文件或文件的内容打印到输出。

示例

  • type filename.txt
  • type a.txt b.txt
  • type *.txt
  • type NUL > tmp.txt
    • 创建一个空文件(空白文件)。

链接

显示命令处理器或操作系统版本。

C:\>VER

Microsoft Windows XP [Version 5.1.2600]

C:\>

一些版本字符串

  • Microsoft Windows [Version 5.1.2600]
    • 适用于 Windows XP
  • Microsoft Windows [Version 6.0.6000]
    • 适用于 Windows Vista
  • ...

单词“version”已本地化。

链接

VERIFY

[edit | edit source]

设置或清除是否验证COPY文件等的写入是否正确。

链接

输出卷标。

链接

外部命令

[edit | edit source]

Windows 命令解释器可用的外部命令是独立的可执行程序文件,由 Microsoft 随操作系统一起提供,或作为标准捆绑在第三方命令解释器中。通过替换程序文件,可以更改这些命令的含义和功能。

许多(但不是全部)外部命令支持“/?”约定,使它们能够将其在线使用信息写入标准输出,然后以状态代码 0 退出。

输出或更改地址解析协议缓存中的项目,该缓存将 IP 地址映射到物理地址。

链接

安排程序在特定时间运行。另请参见SCHTASKS

链接

ATTRIB

[edit | edit source]

输出或设置文件属性。如果没有参数,它将输出当前目录中所有文件的属性。如果没有属性修改指令,它将输出与给定搜索通配符规范匹配的文件和目录的属性。类似于其他操作系统的chmod

修改指令

  • 要添加属性,请在其字母前附加“+”。
  • 要删除属性,请在其字母前附加“-”。
  • 属性
    • A - 已归档
    • H - 隐藏
    • S - 系统
    • R - 只读
    • …以及其他一些。

示例

  • attrib
    • 输出当前目录中所有文件的属性。
  • attrib File.txt
    • 输出文件的属性。
  • attrib +r File.txt
    • 向文件添加“只读”属性。
  • attrib -a File.txt
    • 从文件删除“已归档”属性。
  • attrib -a +r File.txt
    • 从文件删除“已归档”属性,并向文件添加“只读”属性。
  • attrib +r *.txt
    • 作用于一组文件。
  • attrib /S +r *.txt
    • 在子目录中递归操作。

有关更多信息,请键入“attrib /?”。

链接

BCDEDIT

[edit | edit source]

(XP 中没有)。编辑启动配置数据 (BCD) 文件。有关更多信息,请键入“bcdedit /?”。

链接

CACLS

[edit | edit source]

输出或更改任意访问控制列表 (DACL)。另请参见ICACLS。有关更多信息,请键入“cacls /?”。

链接

输出或设置活动代码页编号。有关更多信息,请键入“chcp /?”。

链接

CHKDSK

[edit | edit source]

检查磁盘是否存在磁盘问题,列出这些问题,并在需要时修复它们。有关更多信息,请键入“chkdsk /?”。

链接

CHKNTFS

[edit | edit source]

显示或设置计算机启动时是否应运行系统检查。系统检查使用 Autochk.exe 完成。命令名称中的“NTFS”部分具有误导性,因为该命令不仅适用于 NTFS 文件系统,还适用于 FAT 和 FAT32 文件系统。有关更多信息,请键入“chkntfs /?”。

链接

CHOICE

[edit | edit source]

允许用户通过按下单个键从多个选项中选择一个选项,并将错误级别设置为与所选选项匹配的级别。该命令在 Windows 2000 和 Windows XP 中不存在,在 Windows Vista 中重新引入,并在 Windows 7 和 8 中保留。

示例

  • choice /m "Do you agree"
    • 向用户显示一个是/否问题,将错误级别设置为 1 表示是,设置为 2 表示否。如果用户按下 Ctrl + C,则错误级别为 0。
  • choice /c rgb /m "Which color do you prefer"
    • 向用户显示一个问题,并指示用户的字母。响应用户按下 r、g 或 b,将错误级别设置为 1、2 或 3。

另一种方法是“set /p”;请参见SET

链接

CIPHER

[edit | edit source]

显示加密状态,加密或解密 NTFS 卷上的文件夹。

链接

(XP 中没有此命令,或从 Server 2003 复制) 将管道输入到剪贴板。

示例

  • set | clip
    • 将环境变量列表放到剪贴板。
  • clip < File1.txt
    • 将 File1.txt 的内容放到剪贴板。

链接

调用另一个 Microsoft 的 CMD 实例。

链接

比较文件。另请参阅 FC

链接

COMPACT

[edit | edit source]

显示或更改 NTFS 分区上文件或文件夹的压缩状态。

链接

CONVERT

[edit | edit source]

将卷从 FAT16 或 FAT32 文件系统转换为 NTFS 文件系统。

链接

DEBUG

[edit | edit source]

允许以交互方式在汇编语言、十六进制或 ASCII 中检查文件和内存内容。可在 32 位 Windows(包括 Windows 7)中使用;在 64 位 Windows 中的可用性尚不清楚。在现代 Windows 中,可作为快速查看文件十六进制内容的便捷工具。关键词:十六进制转储、hexdump、十六进制转储、查看十六进制、查看十六进制、反汇编。

Debug 拥有自己的命令行。在命令行上,键入 "?" 以了解 debug 命令。

要查看文件的十六进制,使用文件名作为参数调用 debug.exe,然后在 debug 命令行上重复键入 "d" 后跟回车。

限制

  • 作为 DOS 程序,debug 会对长文件名感到困惑。使用 dir /x 查找 8.3 文件名,然后对该文件名应用 debug。
  • Debug 无法查看较大的文件。

链接

DISKCOMP

[edit | edit source]

比较两张软盘的内容。

链接

DISKCOPY

[edit | edit source]

将一张软盘的内容复制到另一张软盘。

链接

DISKPART

[edit | edit source]

显示和配置磁盘分区的属性。

链接

DOSKEY

[edit | edit source]

最重要的是,创建宏,在其他操作系统中称为别名。此外,还提供与命令历史记录相关的功能以及增强的命令行编辑功能。宏是简短批处理脚本的替代方案。

与宏相关的示例

  • doskey da=dir /s /b
    • 创建单个名为 "da" 的宏。
  • doskey np=notepad $1
    • 创建单个宏,将第一个参数传递给记事本。
  • doskey /macrofile=doskeymacros.txt
    • 从文件加载宏定义。
  • doskey /macros
    • 列出所有定义的宏及其定义。
  • doskey /macros | find "da"
    • 列出所有包含 "da" 作为子字符串的宏定义;另请参阅 FIND

与命令历史记录相关的示例

  • doskey /history
    • 列出完整的命令历史记录。
  • doskey /history | find "dir"
    • 列出命令历史记录中包含 "dir" 作为子字符串的每一行
  • doskey /listsize=100
    • 将命令历史记录的大小设置为 100。

要从命令行获取 doskey 的帮助,键入 "doskey /?"。

链接

DRIVERQUERY

[edit | edit source]

显示所有已安装的设备驱动程序及其属性。

链接

EXPAND

[edit | edit source]

从压缩的 .cab 压缩包文件中解压缩文件。另请参阅 #MAKECAB

链接

比较文件,以一种特殊的方式显示其内容的差异。

示例

  • fc File1.txt File2.txt >NUL && Echo Same || echo Different or error
    • 使用 fc 的错误级别检测差异。错误级别为零表示文件相同;非零可能表示文件不同,也可能表示其中一个文件不存在。

链接

在文件或输入中搜索字符串,输出匹配的行。与 FINDSTR 不同,它无法递归搜索文件夹,无法搜索正则表达式,需要对搜索字符串使用引号,并且将空格视为字面含义而不是逻辑或。

示例

  • find "(object" *.txt
  • dir /S /B | find "receipt"
  • dir /S /B | find /I /V "receipt"
    • 打印 dir 命令输出中所有不匹配的行,忽略字母大小写。
  • find /C "inlined" *.h
    • 不输出匹配的行,而是输出其计数。如果搜索多个文件,则为每个文件输出一个计数数字,前面是一系列破折号,后面是文件名;不输出所有文件中匹配行的总数。
  • find /C /V "" < file.txt
    • 输出 "file.txt" 中的行数,即行计数。完成其他操作系统中 "wc -l" 的工作。通过将 "" 视为行中找不到的字符串来实现。重定向的使用可以防止文件名在行数之前输出。
  • type file.txt | find /C /V ""
    • 与上面类似,但语法不同。
  • type *.txt 2>NUL | find /C /V ""
    • 输出当前文件夹中以 ".txt" 结尾的文件的行计数的总和。"2>NUL" 是标准错误的重定向,它从输出中删除文件名后跟空行的内容。
  • find "Schönheit" *.txt
    • 如果从以 unicode UTF-8 编码保存的批处理文件中运行,则在 UTF-8 编码的 *.txt 文件中搜索搜索词 "Schönheit"。要使此功能正常工作,批处理文件必须不包含记事本在 UTF-8 中保存时写入的字节顺序标记。Notepad++ 是一个示例,它允许您在没有字节顺序标记的情况下写入 UTF-8 编码的纯文本文件。虽然此功能适用于 find 命令,但不适用于 #FINDSTR
  • find "Copyright" C:\Windows\system32\a*.exe
    • 对二进制文件的工作原理与文本文件相同。

链接

FINDSTR

[edit | edit source]

在文件中搜索正则表达式或文本字符串。它可以完成其他操作系统中“grep”命令的一部分工作,但在支持的正则表达式方面要有限得多。

除非使用 /c 选项阻止,否则将正则表达式中的空格视为析取,即逻辑或。

示例

  • findstr /s "[0-9][0-9].*[0-9][0-9]" *.h *.cpp
    • 递归搜索所有以点 h 或点 cpp 结尾的文件,只打印包含两个连续的十进制数字,然后是任何内容,然后是两个连续的十进制数字的行。
  • findstr "a.*b a.*c" File.txt
    • 输出 File.txt 中匹配由空格分隔的两个正则表达式中的任何一个的所有行。因此,其效果是正则表达式的逻辑或
  • echo world | findstr "hello wo.ld"
    • 不匹配。由于空格前的第一个项目看起来不像正则表达式,findstr 将整个搜索词视为普通搜索词。
  • echo world | findstr /r "hello wo.ld"
    • 匹配。使用 /r 强制进行正则表达式处理。
  • findstr /r /c:"ID: *[0-9]*" File.txt
    • 输出 File.txt 中匹配包含空格的单个正则表达式的所有行。使用 /c 阻止将空格视为逻辑或。使用 /r 打开正则表达式处理,默认情况下,/c 将其禁用。要测试这一点,请尝试以下操作
      • echo ID: 12|findstr /r /c:"ID: *[0-9]*$"
        • 匹配。
      • echo ID: 12|findstr /c:"ID: *[0-9]*$"
        • 不匹配,因为搜索字符串不被解释为正则表达式。
      • echo ID: abc|findstr "ID: *[0-9]*$"
        • 尽管 echo 的输出未能匹配完整的正则表达式,但它仍然匹配:搜索被解释为查找匹配“ID:”“*[0-9]*$”的行。
  • findstr /ric:"id: *[0-9]*" File.txt
    • 与前一个示例相同,但以不区分大小写的形式。
    • 虽然 findstr 允许在单个“/”后面累积这种类型的开关,但这在任何命令中都不可能。例如,“dir /bs”不起作用,而“dir /b /s”则起作用。
    • 要测试这一点,请尝试以下操作
      • echo ID: 12|findstr /ric:"id: *[0-9]*$"
      • echo ID: ab|findstr /ric:"id: *[0-9]*$"
  • findstr /msric:"id: *[0-9]*" *.txt
    • 与上面一样,但对所有文件递归执行 /s,显示匹配的文件而不是匹配的行 /m。
  • echo hel lo | findstr /c:"hel lo" /c:world
    • /c 开关可以使用多次来创建逻辑或。
  • echo \hello\ | findstr "\hello\"
    • 不匹配。引号前的反斜杠和其他多个字符充当转义符;因此,\" 匹配 "。
  • echo \hello\ | findstr "\\hello\\"
    • 匹配。传递给 findstr 的双反斜杠代表单个反斜杠。
  • echo \hello\ | findstr \hello\
    • 匹配。传递给 findstr 的单个反斜杠后面都没有用于反斜杠充当转义符的字符。
  • echo ^"hey | findstr \^"hey | more
    • 要搜索引号(双引号),你需要对其进行两次转义:一次是使用插入符号(^)对 shell 进行转义,另一次是使用反斜杠(\)对 findstr 进行转义。
  • echo ^"hey | findstr ^"\^"hey there^" | more
    • 要搜索引号并将搜索词也用引号括起来,则需要对 shell 使用插入符号(^)对包围的引号进行转义。
  • echo //comment line | findstr \//
    • 如果正斜杠(/)是搜索词的第一个字符,则需要使用反斜杠(\)对其进行转义。即使搜索词用引号括起来,也需要进行转义。
  • findstr /f:FileList.txt def.*()
    • 在 FileList.txt 中声明的文件中搜索,每行一个文件。FileList.txt 中的文件名可以包含空格,并且不需要用引号括起来才能正常工作。
  • findstr /g:SearchTermsFile.txt *.txt
    • 搜索 SearchTermsFile.txt 中找到的搜索词,每行一个搜索词。空格不能用于分隔两个搜索词;而是,每行都是一个完整的搜索词。如果至少有一个搜索词匹配,则匹配该行。如果第一个搜索词看起来像正则表达式,则搜索将是正则表达式搜索,但如果它看起来像普通搜索词,则整个搜索将是普通搜索,即使第二个或更后面的搜索词看起来像正则表达式。
  • findstr /xlg:File1.txt File2.txt
    • 输出集合交集:两个文件中都存在的行。
  • findstr /xlvg:File2.txt File1.txt
    • 输出集合差集:File1.txt - File2.txt。
  • findstr /m Microsoft C:\Windows\system32\*.com
    • 对二进制文件的工作原理与文本文件相同。

与“grep”相比,“findstr”正则表达式的局限性

  • 不支持组——“\(”,“\)”。
  • 不支持贪婪迭代器——“*?”。
  • 不支持“前一个的零个或一个”——“?”。
  • 还有更多。

其他限制:如Windows FINDSTR 命令有哪些未记录的功能和限制?中所述,存在各种限制和奇怪的行为。

错误

  • echo bb|findstr "bb baaaa"
    • 在多个 Windows 版本中都无法找到任何内容,但它应该能够找到。

也可以考虑输入“findstr /?”。

链接

FORFILES

[edit | edit source]

根据修改日期和文件名模式查找文件,并对每个找到的文件执行命令。非常有限,尤其是与其他操作系统的 find 命令相比。从 Windows Vista 开始可用。有关更多信息,请键入“forfiles /?”。

示例

  • forfiles /s /d 06/10/2015 /c "cmd /c echo @fdate @path"
    • 对当前文件夹及其子文件夹中于 2015 年 6 月 10 日或之后修改的每个文件,输出文件修改日期和完整文件路径。/d 后的日期格式是特定于区域设置的。因此,可以用来查找最近修改的文件。关键词:最近修改的文件。
  • forfiles /m *.txt /s /d 06/10/2015 /c "cmd /c echo @fdate @path"
    • 与上面一样,但只针对以 .txt 结尾的文件。

链接

forfiles /?

FORMAT

[edit | edit source]

将磁盘格式化为使用 Windows 支持的文件系统(如 FAT、FAT32 或 NTFS),从而覆盖磁盘上的先前内容。请谨慎使用。

链接

FSUTIL

[edit | edit source]

一个功能强大的工具,用于执行与 FAT 和 NTFS 文件系统相关的操作,理想情况下,只有具有广泛操作系统知识的资深用户才能使用它。

链接

GPRESULT

[edit | edit source]

为用户或计算机输出组策略设置等内容。

链接

GRAFTABL

[edit | edit source]

在图形模式下启用扩展字符集的显示。有关更多信息,请键入“graftabl /?”。

链接

显示命令帮助。

示例

  • help
    • 显示 Windows 提供的命令列表。
  • help copy
    • 显示 COPY 命令的帮助,也可以通过键入“copy /?”获得。

链接

ICACLS

[edit | edit source]

(XP 中没有)显示或更改文件或文件夹的任意访问控制列表(DACL)。另请参见CACLS。有关更多信息,请键入“icacls /?”。

链接

IPCONFIG

[edit | edit source]

输出 Windows IP 配置。显示按连接的配置以及该连接的名称(即以太网适配器本地连接)。在其下方,将显示与该连接相关的特定信息,例如 DNS 后缀、IP 地址和子网掩码。

链接

添加、设置或删除磁盘标签。

链接

将文件放入压缩的 .cab 压缩文件中。另请参见 #EXPAND.

链接

一个多用途命令,用于显示设备状态、配置端口和设备等等。

示例

  • mode
    • 输出所有设备(例如 com3 和 con)的状态和配置。
  • mode con
    • 输出 con 设备(命令解释器正在运行的控制台)的状态和配置。
  • mode con cols=120 lines=20
    • 设置当前控制台的列数和行数,导致窗口调整大小,并清除屏幕。此设置不会影响新的控制台实例。关键词:宽屏幕、宽窗口、屏幕大小、窗口大小、调整屏幕大小、调整窗口大小。
  • mode 120, 20
    • 同上:设置列数(120)和行数(20),导致窗口调整大小,并清除屏幕。
  • mode con cols=120
    • 设置当前控制台的列数,导致窗口调整大小,并清除屏幕。它似乎也改变了可见行数,但控制台缓冲区的总行数似乎没有改变。
  • mode 120
    • 同上:设置列数。
  • mode con cp
    • 输出控制台的当前代码页。
  • mode con cp select=850
    • 设置控制台的当前代码页。有关代码页列表,请参阅下面链接的 Microsoft 文档。
  • mode con rate=31 delay=1
    • 设置控制台在按下某个键时重复输入字符的速率和延迟。速率越低,每秒的重复次数越少。

链接

一次输出一个屏幕的文件或多个文件的内容。当重定向到文件时,也会执行一些转换,具体取决于使用的开关。

示例

  • more Test.txt
  • more *.txt
  • grep -i sought.*string Source.txt | more /p >Out.txt
    • 获取非 Windows grep 命令的输出,该命令生成的换行符仅包含 LF 字符,不包含 CR 字符,将 LF 换行符转换为 CR-LF 换行符。CR-LF 换行符也称为 DOS 换行符、Windows 换行符、DOS 换行符、Windows 换行符和 CR/LF 行尾,与某些其他操作系统使用的 LF 换行符相反。
    • 在某些设置中,如果输入包含 LF 换行符和制表符,则似乎会输出乱码。
    • 在某些设置中,对于转换,/p 可能不需要。因此,“more”即使没有 /p 也会转换换行符。
  • more /t4 Source.txt >Target.txt
    • 将制表符转换为 4 个空格。
    • 在某些设置中,制表符转换会自动进行,即使没有 /t 开关。如果是这样,默认情况下是 8 个空格。

开关 /e

  • Windows XP 和 Windows Vista 中“more”的在线文档没有提到此开关。
  • 至少在 Windows XP 和 Windows Vista 中,“more /?” 中提到了 /e 开关。
  • 根据“more /?”,该开关应该启用“more /?” 帮助末尾列出的扩展功能,例如在按下“=”时显示当前行。但是,在 Windows XP 和 Windows Vista 中,即使没有 /e,该功能似乎也默认启用。
  • 假设:在 Windows XP 和 Windows Vista 中,/e 没有任何作用;它存在是为了兼容性原因。

链接

提供各种网络服务,具体取决于使用的命令。每个命令可用的变体

  • net accounts
  • net computer
  • net config
  • net continue
  • net file
  • net group
  • net help
  • net helpmsg
  • net localgroup
  • net name
  • net pause
  • net print
  • net send
  • net session
  • net share
  • net start
  • net statistics
  • net stop
  • net time
  • net use
  • net user
  • net view

链接

OPENFILES

[编辑 | 编辑源代码]

执行与打开文件相关的操作,尤其是那些通过网络由其他用户打开的文件。这些操作包括查询、显示和断开连接。有关更多信息,请键入“openfiles /?”。

链接

语法

  • PING /?
  • PING address
  • PING hostname

通过网络向指定的地址(或指定的 hostname 通过名称查找映射到的第一个 IP 地址)发送 ICMP/IP“回显”数据包,并打印所有收到的响应。

示例

  • ping en.wikibooks.org
  • ping 91.198.174.192
  • ping https://wikibooks.cn/
    • 无法正常工作。

链接

从有缺陷磁盘上的损坏文件中恢复尽可能多的信息。

链接

查询或修改 Windows 注册表。

第一个参数是以下命令之一:query、add、delete、copy、save、load、unload、restore、compare、export、import 和 flags。若要详细了解某个命令,请在后面加上 /?,例如 reg query /?。

链接

用源文件夹中相同名称的文件替换目标文件夹中的文件。

链接

(XP 中没有)复制文件和文件夹。另请参见 XCOPYCOPY.

示例

  • robocopy /s C:\Windows\system C:\Windows-2\system *.dll
    • 将所有以 .dll 结尾的文件从一个目录复制到另一个目录,复制嵌套的目录结构。

链接

运行 DLL 中可用的函数。可用的 DLL 及其函数在不同的 Windows 版本之间有所不同。

示例

  • rundll32 sysdm.cpl,EditEnvironmentVariables
    • 在某些 Windows 版本中,打开用于编辑环境变量的对话框。

链接

控制 Windows 服务,支持启动、停止、查询等操作。Windows 服务类似于进程。Windows 服务要么在自己的进程中托管,要么在 svchost.exe 进程的实例中托管,通常在一个实例中托管多个服务。可以使用 Sysinternals 免费下载的 Process Explorer 查看特定服务的处理器时间使用情况,方法是转到服务的属性,然后转到线程选项卡。另一个可以控制服务的命令是 NETTASKLIST 可以使用 /svc 开关列出托管的服务。

示例

  • sc start wuauserv
    • 启动 wuauserv 服务。
  • sc stop wuauserv
  • sc query wuauserv
  • sc query
    • 输出所有服务的相关信息。
  • sc config SysMain start= disabled
    • 确保 SysMain 服务在启动后处于禁用状态。SysMain 是 SuperFetch 服务,它会通过尝试猜测哪些程序要加载到 RAM 中(以防将来需要使用),然后加载它们,从而导致硬盘频繁活动。请注意,等号前必须没有空格,等号后必须有空格。

链接

SCHTASKS

[edit | edit source]

安排程序在特定时间运行,比 AT 更强大。

链接

类似于 SET,但它影响的是整个机器,而不是当前的控制台或进程。Windows XP 中不可用;Windows Vista 及更高版本可用。

链接

SHUTDOWN

[edit | edit source]

关闭计算机或注销当前用户。

示例

  • shutdown /s
    • 关闭计算机。
  • shutdown /s /t 0
    • 立即关闭计算机。
  • shutdown /l
    • 注销当前用户。

链接

按字母顺序排序,从 A 到 Z 或从 Z 到 A,不区分大小写。无法按数字排序:如果输入包含每行一个整数,“12” 在 “9” 之前。

示例

  • sort File.txt
    • 输出 File.txt 的排序内容。
  • sort /r File.txt
    • 按反向顺序排序,从 Z 到 A。
  • dir /b | sort

链接

SUBST

[edit | edit source]

将驱动器号分配给本地文件夹,输出当前分配,或删除分配。

示例

  • subst p: .
    • 将 p: 分配给当前文件夹。
  • subst
    • 输出之前使用 subst 进行的所有分配。
  • subst /d p
    • 删除 p: 分配。

链接

SYSTEMINFO

[edit | edit source]

显示计算机及其操作系统的配置。

链接

TASKKILL

[edit | edit source]

结束一个或多个任务。

示例

  • taskkill /im AcroRd32.exe
    • 结束所有名为 “AcroRd32.exe” 的进程;因此,结束所有打开的 Acrobat Reader 实例。可以使用 tasklist 查找名称。
  • taskkill /f /im AcroRd32.exe
    • 如上所示,但采用 *强制* 模式。在结束某些没有使用 /f 无法结束的进程时会成功。
  • tasklist | find "notepad"

    taskkill /PID 5792

    • 结束进程 ID(PID)为 5792 的进程(又称任务);假设您已使用 tasklist 找到 PID。

链接

TASKLIST

[edit | edit source]

列出任务,包括任务名称和进程 ID(PID)。

示例

  • tasklist | sort
  • tasklist | find "AcroRd"
  • tasklist | find /C "chrome.exe"
    • 输出名为 “chrome.exe” 的任务数量,这些任务属于 Google Chrome 浏览器。
  • tasklist /svc | findstr svchost
    • 输出在 svchost.exe 进程中托管的 Windows 服务,以及有关进程的常规信息。

链接

TIMEOUT

[edit | edit source]

等待指定秒数,显示剩余秒数,允许用户通过按任意键中断等待。也称为延迟或睡眠。Windows Vista 及更高版本可用。

示例

  • timeout /t 5
    • 等待五秒钟,允许用户通过按任意键取消等待。
  • timeout /t 5 /nobreak
    • 等待五秒钟,忽略用户输入,除了 Ctrl + C。
  • timeout /t 5 /nobreak >nul
    • 如上所示,但没有输出。

Windows XP 中的解决方法

  • ping -n 6 127.0.0.1 >nul
    • 等待五秒钟;-n 后的数字是等待的秒数加 1。

Windows XP 中基于 Perl 的解决方法,需要安装 Perl

  • perl -e "sleep 5"
    • 等待 5 秒。

链接

输出当前目录所有子目录的树形结构,直到任何递归或深度级别。如果与 /F 开关一起使用,则不仅输出子目录,还输出文件。

示例

  • tree
  • tree /f
    • 除了目录外,还包含文件列表。
  • tree /f /a
    • 如上所示,但使用 7 位 ASCII 字符(包括 “+”、“-” 和 “\”)来绘制树形结构。

使用 8 位 ASCII 字符绘制的树形结构片段

├───winevt
│   ├───Logs
│   └───TraceFormat
├───winrm

使用 7 位 ASCII 字符绘制的树形结构片段

+---winevt
|   +---Logs
|   \---TraceFormat
+---winrm

链接

WHERE

[edit | edit source]

输出文件或文件名模式的一个或多个位置,其中文件或模式不需要声明扩展名(如果它在 PATHEXT 中列出,例如 .exe)。默认情况下,在当前目录和 PATH 中搜索。完成某些其他操作系统中 “which” 命令的工作,但更灵活。

Windows 2003、Windows Vista、Windows 7 及更高版本可用;Windows XP 中不可用。下面示例中提供了一个可在 Windows XP 中使用的替代方案。

找不到内部命令,因为它们没有与之匹配的 .exe 文件。

示例

  • where find
    • 输出 find 命令的位置,可能是 “C:\Windows\System32\find.exe”。只要扩展名在 PATHEXT 中列出,就不需要指定 .exe 扩展名,默认情况下它已列出。
    • 如果路径中存在多个 find 命令,则输出两个命令的路径。在某些情况下,它可能会输出以下内容

      C:\Windows\System32\find.exe
      C:\Program Files\GnuWin32\bin\find.exe

  • for %i in (find.exe) do @echo %~$PATH:i
    • 输出 Windows XP 中 “find.exe” 的位置。与 where 命令不同,名称必须包含 “.exe”。
  • where /r . Tasks*
    • 从当前文件夹递归搜索名称匹配 “Task*” 的文件。类似于 “dir /b /s Tasks*”。/r 开关禁用在 PATH 中的文件夹中搜索。
  • where *.bat
    • 输出当前目录和 PATH 中的目录中所有 .bat 文件。因此,输出所有无需输入其完整路径即可运行的 .bat 文件。
  • where ls*.bat
    • 如上所示,还限制 .bat 文件名的开头。
  • where ls*
    • 如上所示,但对扩展名没有限制。如果在当前目录或路径中,则查找 lsdisks.bat、lsmice.pl 和 lsmnts.py。
  • where *.exe *.com | more
    • 输出路径和当前文件夹中无数的 .exe 和 .com 文件,包括 C:\Windows\System32 中的文件。
  • where $path:*.bat
    • 输出路径中的 .bat 文件,但不出于当前文件夹中的文件,除非当前文件夹在 PATH 中。可以使用包含目录列表的其他环境变量来代替路径。
  • where $windir:*.exe
    • 输出在 WINDIR 环境变量中声明的文件夹中找到的 .exe 文件。
  • where $path:*.bat $windir:*.exe
    • 可以进行组合。输出与这两个查询匹配的所有文件。
  • where /q *.bat && echo Found
    • 抑制标准输出和错误输出,但设置错误级别,允许对其进行测试。无论是否使用 /q,都会设置错误级别。

链接

启动 Windows 管理体系结构命令行 (WMIC),或者在给出参数的情况下,将参数作为命令传递给 WMIC。Windows XP Home 中没有。有关更多信息,请键入 "wmic /?"。

示例

  • wmic logicaldisk get caption,description
    • 列出在驱动器号下可访问的驱动器(磁盘),无论本地硬盘驱动器、CD-ROM 驱动器、可移动闪存驱动器、网络驱动器还是使用 #SUBST 创建的驱动器。
  • wmic logicaldisk get /format:list
    • 输出 "logicaldisk" 对象的所有属性,每行一个属性。
  • wmic logicaldisk get /format:csv
  • wmic
    Control + C
    • 进入 wmic,然后中断它。一个副作用是控制台缓冲区变得非常宽,并且屏幕因此可以使用鼠标水平调整大小。这是 wmic 设置控制台列数过高的结果,您可以使用 mode con 验证。您也可以通过键入 mode 1500 来实现类似的效果。另请参阅 #MODE
  • wmic datafile where name="C:\\Windows\\System32\\cmd.exe" get Version /value
    • 输出 cmd.exe 的版本,该版本应接近 Windows 版本。
  • wmic os get TotalVisibleMemorySize
    • 输出总物理内存大小。
  • wmic os get TotalVirtualMemorySize
    • 输出总虚拟内存大小。
  • wmic os get /format:list
    • 输出 "os" 对象的所有属性,每行一个属性。

链接

以比 COPY 更高级的方式复制文件和目录,在 Windows Vista 及更高版本中被弃用,有利于使用 ROBOCOPY。键入 xcopy /? 以了解详细信息,包括无数选项。

示例

  • xcopy C:\Windows\system
    • 复制所有文件,但不复制嵌套文件夹中的文件,从源文件夹 ("C:\Windows\system") 复制到当前文件夹。
  • xcopy /s /i C:\Windows\system C:\Windows-2\system
    • 复制所有文件和文件夹到任何嵌套深度(通过 "/s"),从源文件夹 ("C:\Windows\system") 复制到 "C:\Windows-2\system",如果 "Windows-2\system" 不存在则创建它(通过 "/i")。
  • xcopy /s /i /d:09-01-2014 C:\Windows\system C:\Windows-2\system
    • 如上所述,但仅复制 2014 年 9 月 1 日或之后更改的文件。请注意,即使您使用的是非美国地区的 Windows,也使用月优先的约定。
  • xcopy /L /s /i /d:09-01-2014 C:\Windows\system C:\Windows-2\system
    • 如上所述,但在测试模式下通过 /L (仅列表、仅输出、仅显示)。因此,不执行任何实际复制,只是列出将要复制的内容。
  • xcopy /s /i C:\Windows\system\*.dll C:\Windows-2\system
    • 与上述示例之一类似,但仅复制以 .dll 结尾的文件,包括嵌套文件夹中的文件。

链接

[编辑 | 编辑源代码]
  • PowerShell -- 用于脚本 Windows 操作系统的现代技术
  • VBScript 编程 -- 一种遗留的 Windows 脚本技术,其语法类似于 Visual Basic
[编辑 | 编辑源代码]
华夏公益教科书