跳转到内容

Windows 批处理脚本

50% developed
来自维基教科书,开放世界中的开放书籍

本书描述并展示了如何使用微软提供的命令解释器 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,它们的微软提供的命令解释器实际上是 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 对于 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 之间。另见#Calculation.
%ERRORLEVEL% 最后一个执行的命令或最后一个调用的批处理脚本返回的错误级别。另见#Error level.
%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”添加到变量中,您可以确保即使在没有“.pl”扩展名的情况下键入,Perl 程序也能从命令行运行。因此,您可以键入“mydiff a.txt b.txt”而不是键入“mydiff.pl a.txt b.txt”。

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

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

链接

PROMPT

[edit | edit source]

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

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

字符 扩展结果
$$ $ 字符本身
$A & 符号,也称为与号。这是一个便利的符号,因为使用 SET 命令很难在 PROMPT 环境变量的值中放置一个字面上的&
$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 The error level is zero, meaning success.
  • if %errorlevel% neq 0 echo The error level is non-zero, meaning failure.
  • if errorlevel 1 echo The error level is >= 1, meaning failure via positive error level.
    • 不涵盖通过负错误级别发生的失败。请注意“>=”部分:这与 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" 测试,它似乎是测试成功,但在负数上通过:它测试的是“非 errorlevel >= 1”,也就是“errorlevel <= 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
)

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

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

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

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

在 Windows Vista 机器上,根据经验确定,最大可能的参数数量大于 4000。在 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
    • 递归列出目录内容,显示完整路径。

链接

通配符

[编辑 | 编辑源代码]

许多命令接受文件名通配符 - 不代表自身的字符,可以匹配一组文件名。

通配符

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

示例

  • 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 等。

链接

用户输入

[编辑 | 编辑源代码]

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

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

百分号波浪线

[编辑 | 编辑源代码]

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

以下语法扩展到有关作为 %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 /?"。

链接

函数又称子程序,可以使用 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

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

链接

批处理脚本可以使用 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"
    • 由于 ">>" 运算符是算术右移,它保留了 32 位有符号整数的底层位表示中的最高位,因此输出 -1 作为结果。注意,-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 中的语法,请参见 #百分号波浪线
  • 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 命令行时(在按下 Windows + R 后键入 cmd.exe 后出现),可以使用多个键盘快捷键,包括功能键

  • 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:打开一个基于字符的弹出窗口,显示命令历史记录,并允许您使用箭头键和回车键选择命令。 在弹出窗口中按回车键后,命令立即执行。
  • 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 命令,显示该行的第二个字段或列,在本例中为 b。 使用 $F[2] 显示第三个字段;索引从零开始。 本机解决方案: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 指南 维基教科书中了解更多关于这些命令的信息。 注意,依赖于这些命令的批处理程序不能保证在其他 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 语句。
  • 没有从 C 语言中知道的用于循环控制的 break 和 continue 语句。
  • 没有真正的自定义函数;可以使用标签、调用和 %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
    • 回显即使是较小的数字(在本例中为 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
  • 退出 /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 中的语法,请参见 #百分号波浪线

/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
    • 将字符串解析为以“:”分隔的标记。
    • 引号表示该字符串不是文件名。
    • 即使 %b 和 %c 在“do”之前的命令部分中没有明确提及,第二个和第三个标记也会存储在 %b 和 %c 中。
    • 两个连续的冒号被视为一个分隔符;%c 不是 "",而是 "Third"。
    • 完成其他操作系统中 cut 命令的一些工作。
  • for /f "tokens=1-3* delims=:" %a in ("First:Second::Third:Fourth:Fifth") do @echo %c-%b-%a: %d
    • 如上所述,只是第 4 个和第 5 个项目被捕获在 %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
)

链接

输出或设置要为文件类型执行的命令。另请参见 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"
    • 在当前目录中创建一个包含空格的目录。

链接

MD 的同义词。

创建符号链接或其他类型的链接。从 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%
    • 将 C:\Users\Joe Hoe\Scripts 扩展到路径,仅适用于 cmd.exe 的进程。
  • path ;
    • 清空路径。
  • echo %path% | perl -pe "s/;/\n/g" | sort
    • 如果你安装了 perl,则显示路径中的文件夹(已排序)。

链接

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

链接

更改到从目录堆栈中弹出的驱动器和目录。目录堆栈使用 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
    • 输出以“home”开头的变量的环境变量列表及其值,不区分大小写,格式为 VAR=VALUE,每行一个变量。
  • 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 )
    • 用计算结果设置 result 变量。另请参见 #计算
  • 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

链接

SHIFT

[edit | edit source]

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

链接

START

[edit | edit source]

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

示例

  • 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#特殊变量名称 中的 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 [版本 5.1.2600]
    • 适用于 Windows XP
  • Microsoft Windows [版本 6.0.6000]
    • 适用于 Windows Vista
  • ...

“版本”一词已本地化。

链接

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 中,可用作快速查看文件十六进制内容的黑客工具。关键词:十六进制转储、十六进制转储、十六进制转储、查看十六进制、查看十六进制、反汇编程序。

Debug 提供自己的命令行。在命令行上,键入“?”以查找有关调试命令的信息。

要查看文件的十六进制,请使用文件名作为参数调用 debug.exe,然后在调试命令行上反复键入“d”并按回车。

局限性

  • 作为 DOS 程序,debug 会对长文件名产生问题。使用 dir /x 查找 8.3 文件名,然后对该文件名应用调试。
  • 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
    • 不仅适用于文本文件,还适用于二进制文件。

"findstr" 的正则表达式限制,与 "grep" 相比

  • 不支持组 - “\(","\)”。
  • 不支持贪婪迭代器 - "*?"。
  • 不支持 "前一个的零个或一个" - "?"。
  • 等等。

其他限制:存在各种限制和奇怪的行为,如 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 /?

格式化磁盘以使用 Windows 支持的文件系统(如 FAT、FAT32 或 NTFS),从而覆盖磁盘上的先前内容。 使用时要格外小心。

链接

一个功能强大的工具,执行与 FAT 和 NTFS 文件系统相关的操作,理想情况下仅供拥有广泛操作系统知识的高级用户使用。

链接

输出用户或计算机的组策略设置等信息。

链接

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

链接

显示命令帮助。

示例

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

链接

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

链接

输出 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 地址
  • PING 主机名

通过网络向指定地址(或通过名称查找映射到的指定主机名的第一个 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,转到服务的属性,然后查看“线程”选项卡,找到特定服务的处理器时间使用情况。另一个可以控制服务的命令是 NET。使用 /svc 开关,TASKLIST 可以列出托管的服务。

示例

  • sc start wuauserv
    • 启动 wuauserv 服务。
  • sc stop wuauserv
  • sc query wuauserv
  • sc query
    • 输出有关所有服务的信息。
  • sc config SysMain start= disabled
    • 确保启动后 SysMain 服务已禁用。SysMain 是 SuperFetch 服务,通过尝试猜测哪些程序将在使用时加载到 RAM 中并将其加载,从而导致反复的硬盘驱动器活动。请注意,等号前后的空格必须分别为 0 个和 1 个。

链接

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

链接

SET 相似,但会影响整个计算机,而不是当前控制台或进程。Windows XP 中不可用;Windows Vista 及更高版本中可用。

链接

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

示例

  • 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 p: .
    • 将 p: 分配给当前文件夹。
  • subst
    • 输出之前使用 subst 做出的所有分配。
  • subst /d p
    • 删除 p: 分配。

链接

SYSTEMINFO

[编辑 | 编辑源代码]

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

链接

结束一个或多个任务。

示例

  • 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。

链接

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

示例

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

链接

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

示例

  • timeout /t 5
    • 等待五秒钟,允许用户通过按一个键取消等待。
  • timeout /t 5 /nobreak
    • 等待五秒钟,忽略用户输入,除非是 Control + C。
  • timeout /t 5 /nobreak >nul
    • 与上面相同,但不输出任何内容。

Windows XP 中的解决方法

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

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

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

链接

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

示例

  • tree /f
    • 除了目录之外,还包括列表中的文件。
  • tree /f /a
    • 如上所述,但使用 7 位 ASCII 字符,包括 "+"、"-" 和 "\" 来绘制树。

使用 8 位 ASCII 字符的树的片段

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

使用 7 位 ASCII 字符的树的片段

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

链接

在哪里

[编辑 | 编辑源代码]

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

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

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

示例

  • where find
    • 输出 find 命令的位置,可能是 "C:\Windows\System32\find.exe"。只要 .exe 扩展名在 PATHEXT 中列出,就不需要指定 .exe 扩展名,默认情况下它在 PATHEXT 中列出。
    • 如果路径中存在多个 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 中。除了 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
[编辑 | 编辑源代码]
华夏公益教科书