运维必备 | Win批处理(Batch)编程常用DOS命令汇总收藏备查

2023-10-31 17:21:17 浏览数 (3)

本文为作者原创文章,为尊重作者劳动成果禁止非授权转载,若需转载请在【全栈工程师修炼指南】公众号留言,或者发送邮件到 master@weiyigeek.top 中我将及时回复。

0x00 批处理脚本基础命令

echo 命令 - 终端输出字符串

描述: 打开回显或关闭请求回显功能或显示消息,如果没有任何参数echo 命令将显示当前回显设置。

语法参数:

代码语言:javascript复制
echo [{on off}] [message]

示例演示:

代码语言:javascript复制
# 1.命令行输出字符串
(echo weiyigeek)
echo "weiyigeek.top"
# 换行输出
echo.

# 2.输出系统预定义环境变量
echo �%
  # C:UsersWeiyiGeek
echo %Userprofile%
  #  C:UsersWeiyiGeek
echo %Userprofile%download
  # C:UsersWeiyiGeekdownload

# 3.批处理脚本中使用示例
@echo off
echo hello world

cls 命令 - 清理屏幕显示

描述: 此命令用于清理windows cmd中界面显示的数据,即达到清屏的效果, 该命令使用非常简单执行cls即可。

代码语言:javascript复制
cls /?
# 清除屏幕。
CLS

pause 命令 - 暂停批处理程序

描述: 此命令主要用于暂停批处理程序,可以请按任意键继续。

示例演示:

在这个例子中,驱动器 F 中磁盘上的所有文件均复制到 d:back 中。

显示的注释提示您将 另一张磁盘放入驱动器 F 时,pause 命令会使程序挂起,以便您更换磁盘,然后按任意键继续处理。

代码语言:javascript复制
@echo off
:begin
copy f:*.* d:back
echo Please put a new disk into driver F
pause   # 关键点
goto begin

@ 命令 - 不显示原始命令到终端中

描述: 表示不显示@后面的命令,在入侵过程中(例如使用批处理来格式化敌人的硬盘)自然不 能让对方看到你使用的命令啦。

代码语言:javascript复制
@echo off
@echo Now initializing the program,please wait a minite...
@format X: /q /u /autoset

温馨提示: format 命令是不可以使用/y这个参数的,可喜的是微软留了个autoset这个参数给我们效果和/y是一样的。

rem 命令 - 注释字符串或者命令

描述: 在C语言中相当与 /*--------*/, 它并不会被执行, 只是起一个注释的作用,便于别人阅读和你自己日后修改。

语法示例:

代码语言:javascript复制
REM 注释信息[Message]
@REM 注释信息[Message]
:: 注释信息[Message]

示例演示:

代码语言:javascript复制
REM Here is the description, blog.weiyigeek.top ?
@REM Here is the description, blog.weiyigeek.top ?
:: Here is the description, blog.weiyigeek.top ?

goto 命令 - 调转到指定命令

描述:指定跳转到:标签,找到标签后,程序将处理从下一行开始的命令。

语法参数:

代码语言:javascript复制
goto label # label是参数指定所要转向的批处理程序中的行。

示例演示:

代码语言:javascript复制
if {%1}=={} goto noparms
if {%2}=={} goto noparms
@Rem check parameters if null show usage
:noparms
echo Usage: monitor.bat ServerIP PortNumber
goto end

温馨提示: 标签的名字可以随便起,但是最好是有意义的字母啦,字母前加个:label用来表示这个字母是标签,goto命令就是根据这个:label来寻找下一步跳到到那里, 最好有一些注释说明这样你别人看起来才会理解你的意图。

call 命令 - 调用子批处理

描述: 此命令实现从一个批处理程序调用另一个批处理程序,并且不终止父批处理程序,其命令接受用作调用目标的标签,如果在脚本或批处理文件外使用 Call,它将不会在命令行中起作用。

语法参数:

代码语言:javascript复制
call [[Drive:][Path] FileName [BatchParameters]] [:label [arguments]]

# 参数
[Drive:}[Path] FileName  指定批处理绝对路径,其中filename参数必须具有 .bat 或 .cmd 扩展名
BatchParameters          指定批处理程序所需的命令行参数
label [arguments]        指定批处理中的标签名以及参数

温馨提示: 一个新的批文件上下文由指定的参数所创建,控制在卷标被指定后传递到语句,您必须通过达到批脚本文件末两次来 "exit" 两次, 第一次读到文件末时,控制会回到 CALL 语句的紧后面,第二次会退出批脚本。

温馨提示: 在脚本中获取命令行参数时,使用批脚本里的 %* 指出所有的参数 (如 %1 %2 %3 %4 %5 ...) 分别对应指定位置的参数值。

示例演示:

  • 一个 call 与 goto 使用的经典案例:
代码语言:javascript复制
@echo off
@REM 一个 call 与 goto 使用的经典案例
for /l %%j in (1,1,5) do (
@REM 此处是值得学习的
  if %%j==5 (goto :stop) else (call :multiply %%j %%j)   
)

@REM 注意此处是使用 %1 %2 ... %9 来接收变量值。
:multiply %1 %2   
set /a a=%1*%2
echo %1*%2=%a%

:stop
echo "!!! Over !!!!"

执行结果:

代码语言:javascript复制
Day01>12.call-goto.bat
1*1=1
"!!! Over !!!!"
2*2=4
"!!! Over !!!!"
3*3=9
"!!! Over !!!!"
4*4=16
"!!! Over !!!!"
"!!! Over !!!!"

0x01 批处理脚本终端配置

title 命令 - 设置CMD窗口标题名字

描述: 此命令用于更改CMD窗口标题名字。

示例演示:

代码语言:javascript复制
title 这是标题
title 这是批处理的执行终端的标题

温馨提示: 如果想调整终端窗口显示大小,我们可以执行如下命令mode con: cols=1024 lines=30设置一个30行1024列的终端。

color 命令 - 设置控制台前后景颜色

描述: 此命令在编写脚本中通常用于设置默认的控制台前景和背景颜色。

语法参数

代码语言:javascript复制
COLOR [attr]
attr  指定控制台输出的颜色属性

# 参数说明
# 颜色属性由两个十六进制数字指定,其中第一位为背景颜色,第二位为前景颜色,每个数字可以为以下任何值之一:
0 = 黑色      8 = 灰色
1 = 蓝色      9 = 淡蓝色
2 = 绿色      A = 淡绿色
3 = 湖蓝色    B = 淡浅绿色
4 = 红色      C = 淡红色
5 = 紫色      D = 淡紫色
6 = 黄色      E = 淡黄色
7 = 白色      F = 亮白色

温馨提示: 如果没有给定任何参数,该命令会将颜色还原到 CMD.EXE 启动时的颜色(复原黑底白字),这个值来自当前控制台窗口、/T 命令行开关 或DefaultColor 注册表值。

示例演示:

代码语言:javascript复制
@REM 设置亮白色背景上产生亮红色的字,其不区分大小写但是还是建议使用大写表示。
COLOR FC
COLOR fc

@REM 恢复默认的黑底白字。
Color

@REM 设置黑底绿字表示执行成功
color 02
color 0A

@REM 设置黑底黄字表示执行成功
color 06
color 0E

@REM 设置黑底红字、红底白字表示执行成功
color 04
color 47

chcp 命令 - 终端编码配置

描述: 显示活动控制台代码页数量,或更改该控制台的活动控制台代码页,如果在没有参数的情况下使用,则显示活动控制台代码页的编号。

语法参数:

代码语言:javascript复制
# 使用语法:
chcp [nnn]
# 参数 nnn 指定代码页编号。

# 下表列出了所有支持的代码页及其国家(地区)或者语言:
# 代码页 国家(地区)或语言
437 美国 - 无法打印出非ascii字符
708 阿拉伯文(ASMO 708)
720 阿拉伯文(DOS)
850 多语言(拉丁文 I)
852 中欧(DOS) - 斯拉夫语(拉丁文 II)
855 西里尔文(俄语)
857 土耳其语
860 葡萄牙语
861 冰岛语
862 希伯来文(DOS)
863 加拿大 - 法语
865 日耳曼语
866 俄语 - 西里尔文(DOS)
869 现代希腊语
874 泰文(Windows)
932 日文(Shift-JIS)
936 中国 - 简体中文(GB2312) - 常用
949 韩文
950 繁体中文(Big5)
1200 Unicode
1201 Unicode (Big-Endian)
1250 中欧(Windows)
1251 西里尔文(Windows)
1252 西欧(Windows)
1253 希腊文(Windows)
1254 土耳其文(Windows)
1255 希伯来文(Windows)
1256 阿拉伯文(Windows)
1257 波罗的海文(Windows)
1258 越南文(Windows)
20866 西里尔文(KOI8-R)
21866 西里尔文(KOI8-U)
28592 中欧(ISO)
28593 拉丁文 3 (ISO)
28594 波罗的海文(ISO)
28595 西里尔文(ISO)
28596 阿拉伯文(ISO)
28597 希腊文(ISO)
28598 希伯来文(ISO-Visual)
38598 希伯来文(ISO-Logical)
50000 用户定义的
50001 自动选择
50220 日文(JIS)
50221 日文(JIS-允许一个字节的片假名)
50222 日文(JIS-允许一个字节的片假名 - SO/SI)
50225 韩文(ISO)
50932 日文(自动选择)
50949 韩文(自动选择)
51932 日文(EUC)
51949 韩文(EUC)
52936 简体中文(HZ)
65000 Unicode (UTF-7)
65001 Unicode (UTF-8) -- 常用

使用示例

代码语言:javascript复制
# 1.不带参数键入 CHCP 以显示活动代码页编号。
c:WindowsSystem32>chcp
活动代码页: 936

# 2.设置cmd终端编码为UTF-8
c:WindowsSystem32>chcp 65001
Active code page: 65001

prompt - 配置终端命令行格式化提示符

描述: 此处命令用于更改 cmd.exe 命令行格式化提示符,其类似于Shell中针对PS1变量进行设置,从而自定义终端命令行格式。

语法参数:

代码语言:javascript复制
PROMPT [text]
# 参数
text 指定新的命令提示符字符串

# 命令行提示符可以由普通字符及下列特定代码组成:
$A  & (短 and 符号)
$B  | (管道)
$C  ( (左括弧)
$D  当前日期
$E  Escape 码(ASCII 码 27)
$F  ) (右括弧)
$G  > (大于符号)
$H  Backspace (擦除前一个字符)
$L  < (小于符号)
$N  当前驱动器
$P  当前驱动器及路径
$Q  = (等号)
$S    (空格)
$T  当前时间
$V  Windows 版本号
$_  换行
$$  $ (货币符号)
# 若命令扩展被启用,PROMPT 命令会支持下列格式化字符:
$   根据 PUSHD 目录堆栈的深度,零个或零个以上加号( )字符一个推的层一个字符
$M  如果当前驱动器不是网络驱动器,显示跟当前驱动器号或空字符串有关联的远程名

示例演示:

代码语言:javascript复制
# 1.将Windows终端命令行设置与Linux风格
prompt [weiyigeek@localhost] $P$S$$$S  

# 2.获取真实的用户名与主机名称放置在格式化命令行中。
for /f "delims=" %a in ('whoami') do @set userdoamin=%a
set userdoamin=%userdoamin:=@%
echo %userdoamin%
prompt [%userdoamin% $P$S$T]$S$$$S

例如:执行 prompt weiyigeek 命令,那么命令行提示符就会变成weiyigeek,你输入exit退出窗口【注意:这个仅在当前窗口生效】,若想永久生效要设置注册表项或者设置环境变量,

Windows 10 及以上系统请按照以下步骤进行操作;

  1. 打开"控制面板":按下Win X键,然后选择"控制面板"。
  2. 在控制面板中,选择"系统和安全",然后选择"系统"。
  3. 在系统窗口中,选择"高级系统设置"。
  4. 在弹出的"系统属性"窗口中,选择"高级"选项卡,然后点击"环境变量"按钮。
  5. 在"用户变量"或"系统变量"部分,找到名为Prompt"的变量(如果没有,请点击"新建"按钮创建一个)。
  6. 编辑"Prompt"变量的值,输入您想要设置的新prompt命令。
  7. 点击"确定"保存更改。

Windows 7 以前请按照以下步骤进行操作;

  1. 打开注册表编辑器:按下Win R键,输入"regedit",然后按Enter键。
  2. 导航到以下路径:HKEY_CURRENT_USERSoftwareMicrosoftCommand Processor
  3. 在右侧窗格中,找到名为"Prompt"的字符串值(如果没有,请右键单击空白处,选择"新建" -> "字符串值",然后将其命名为"Prompt")。
  4. 双击"Prompt"值,然后在"数值数据"字段中输入您想要设置的新prompt命令。
  5. 单击"确定"保存更改。
  6. 关闭注册表编辑器。

现在,您下次打开命令提示符时,将会看到您所设置的新prompt命令。


0x02 批处理脚本操作执行命令

type 命令 - 显示文本文件的内容

描述:此命令用于在cmd中打开文本文件并输出内容到终端, 该命令使用也是非常的简单。

语法参数

代码语言:javascript复制
TYPE [drive:][path]filename

示例演示:

代码语言:javascript复制
echo "weiyigeek.top" >> weiyigeek.txt
type weiyigeek.txt

偷偷的告诉你哟?极客全栈修炼】微信小程序已开放

可直接在微信里面直接浏览博主文章哟,后续将上线更多有趣的小工具。


date 与 time 命令 - 获取设置系统的日期时间

描述: 使用上述两个命令,可以帮助我们获取当前系统的日期时间以及设置系统日期时间。

语法参数:

代码语言:javascript复制
# 1.显示或设置日期
DATE [/T | date]

# 2.显示或设置时间
TIME [/T | time]

示例演示:

代码语言:javascript复制
# 交互式设置日期时间
date && time 

# 命令行式设置日期时间
date "2023-07-15"
time "12:13:14"

# 获取日期时间
date /t  >> 2017/04/17 周一
time /t  >> 22:32

温馨提示: 在批处理中除了使用上述命令外,我们还可使用�te%%time%环境变量进行获取日期时间, 例如 echo �te% %time%

start 命令 - 启动程序或打开网页

描述: 此命令主要用于启动一个单独的窗口运行指定的程序或命令。

语法参数

代码语言:javascript复制
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
      [/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
      [/NODE <NUMA node>] [/AFFINITY <hex affinity mask>] [/WAIT] [/B]
      [command/program] [parameters]

# 参数说明:
"title"     在窗口标题栏中显示的标题。
/D path        启动目录
/I           新的环境将是传递给 cmd.exe 的原始环境,而不是当前环境
/MIN         以最小化方式启动窗口
/MAX         以最大化方式启动窗口

/SEPARATE    在单独的内存空间中启动 16 位 Windows 程序(separate)
/SHARED      在共享内存空间中启动 16 位 Windows 程序(shared)

/LOW         在 IDLE 优先级类中启动应用程序
/NORMAL      在 NORMAL 优先级类中启动应用程序
/HIGH        在 HIGH 优先级类中启动应用程序
/REALTIME    在 REALTIME 优先级类中启动应用程序
/ABOVENORMAL 在 ABOVENORMAL 优先级类中启动应用程序
/BELOWNORMAL 在 BELOWNORMAL 优先级类中启动应用程序

NODE        将首选非一致性内存结构 NUMA 节点指定为十进制整数
AFFINITY    将处理器关联掩码指定为十六进制数字,进程被限制在这些处理器上运行当 /AFFINITY 和 /NODE 结合时,会对关联掩码进行不同的解释。指定关联掩码,正如 NUMA 节点的处理器掩码正确移动到零位起始位置一样。进程被限制在指定关联掩码和 NUMA 节点之间的那些通用处理器上运行。如果没有通用处理器,则进程被限制在指定的 NUMA 节点上运行
/B           启动应用程序,但不创建新窗口,应用程序已忽略 ^C 处理,除非应用程序启用 ^C 处理,否则 ^Break 是唯一可以中断该应用程序的方式.

/WAIT        启动应用程序并等待它终止。
command/program 如果它是内部 cmd 命令或批文件,则该命令处理器是使用cmd.exe 的 /K 开关运行的。这表示运行该命令之后,该窗口将仍然存在如果它不是内部 cmd 命令或批文件,则它就是一个程序,并将作为一个窗口化应用程序或控制台应用程序运行      
parameters  这些是传递给 command/program 的参数。

温馨提示: 注意在 64 位平台上不支持 SEPARATE 和 SHARED 选项。

温馨提示: 如果命令扩展被启用,我们还可通过命令行或 START 命令的外部命令

示例演示:

  • 1.通过指定 /NODE,可按照利用 NUMA 系统中的内存区域的方式创建进程。

例如,可以创建两个完全通过共享内存互相通信的进程以共享相同的首选 NUMA 节点,从而最大限度地减少内存延迟。如有可能,它们即会分配来自相同 NUMA 节点的内存,并且会在指定节点之外的处理器上自由运行。

代码语言:javascript复制
# 1.下面的两个进程可被进一步限制在相同 NUMA 节点内的指定处理器上运行。
start /NODE 1 application1.exe
start /NODE 1 application2.exe

# 2.下面的 application1 在节点的两个低顺序处理器上运行,而 application2在该节点的其后两个处理器上运行,此处假定指定节点至少具有四个逻辑处理器,注意节点号可更改为该计算机的任何有效节点号,而无需更改关联掩码。
start /NODE 1 /AFFINITY 0x3 application1.exe
start /NODE 1 /AFFINITY 0xc application2.exe
  • 2.通过start将文件名作为命令键入,非可执行文件可以通过文件关联调用,如果执行的命令行的第一个符号没有扩展名,CMD.EXE 会使用PATHEXT环境变量(与PATH变量类似)的数值来决定要以什么顺序寻找哪些扩展名。

例如,WORD.DOC 会调用跟 .DOC 文件扩展名关联的应用程序

代码语言:javascript复制
# start [/max或者/min] 程序名或命令,以及根据后缀打开对应对应文件。
start /max calc
start /min explorer
start /max ckcore.txt

# 打开一个带有标题title的cmd,以最大与最小化的形式。
C:>start "最大化的窗口" /max               
C:>start "最小化的窗口" /min
  • 3.使用start命令打开一个网站或者一个目录。
代码语言:javascript复制
# 在一个批处理中执行批处理的格式, 切换工作目录到 d:calc 并打开 calc.bat 批处理。
start /d "d:calc" calc.bat

# 使用其打开当前目录资源文件夹
start c:usersweiyigeek

# 使用其打开要访问的网站。
start https://weiyigeek.top

timeout 命令 - 延迟执行脚本或者命令

描述:此工具接受超时参数,等候一段指定的时间(秒)或等按任意键,它还接受一个参数,忽视按键,等于Linux中的sleep命令。

语法参数:

代码语言:javascript复制
# 语法:
TIMEOUT [/T] timeout [/NOBREAK]

# 参数列表:
/T        timeout      指定等候的秒数,有效范围从 -1 到 99999 秒。
/NOBREAK               忽略按键并等待指定的时间。
注意: 超时值 -1 表示无限期地等待按键

示例演示:

代码语言:javascript复制
TIMEOUT /T 10
TIMEOUT /T 300 /NOBREAK
TIMEOUT /T -1

choice 命令 - 提示信息与对应参数选项命令

描述: 该工具允许用户从选择列表选择一个项目并返回所选项目的索引, 即使用此命令可以让用户输入一个字符,从而运行不同的命令。

语法参数:

代码语言:javascript复制
CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]

# 参数列表:
/C    choices       指定要创建的选项列表。默认列表是 "YN", 其对应ERRORLEVEL 返回码为1234
/N                  在提示符中隐藏选项列表。提示前面的消息得到显示,选项依旧处于启用状态
/CS                允许选择分大小写的选项。在默认情况下,这个工具是不分大小写的
/T    timeout      做出默认选择之前,暂停的秒数。可接受的值是从 0到 9999。如果指定了 0,就不会有暂停,默认选项会得到选择
/D    choice        在 nnnn 秒之后指定默认选项。字符必须在用 /C 选项指定的一组选择中; 同时,必须用 /T 指定 nnnn
/M    text          指定提示之前要显示的消息。如果没有指定,工具只显示提示

温馨提示: 当用户选择/c中列举的选项时,列出的第一个选择返回 1,第二个选择返回 2,我们可%ERRORLEVEL%环境变量(类似与LINUX中$?)来获取从选择集选择的键索引。如果用户按的键不是有效的选择,该工具会发出警告响声。如果该工具检测到错误状态,它会返回 255 的ERRORLEVEL 值, 如果用户按 Ctrl Break 或 Ctrl C 键,该工具会返回 0 的 ERRORLEVEL 值。

示例演示:

  • 1.在一个批程序中使用 ERRORLEVEL 参数时,将参数降序排列, 注意用if errorlevel判断返回值时, 要按返回值从高到低排列, 不能含有choice.bat关键字命名的bat:
代码语言:javascript复制
@echo off
choice /C dme /M "defrag,mem,end"
if errorlevel 3 goto end
if errorlevel 2 goto mem
if errorlevel 1 goto defrag

:defrag
c:dosdefrag
goto end

:mem
mem
goto end

:end
echo good bye

脚本说明: 此批处理运行后,将显示“defrag,mem,end[D,M,E]?” ,用户可选择d m e,然后if语句根据用户的选择作出判断,d表示执行标号为defrag的程序段,m表示执行标号为mem的程序段,e表示执行标号为end的程序段,每个程序段最后都以goto end将程序跳到end标号处,然后程序将显示good bye 批处理运行结束, 执行结果如下:

代码语言:javascript复制
# 参数 M 选项提示,参数 C 可选选项
choice /c:dme /M "defrag,mem,end"

# 执行后将显示如下提示,以及选项对应的ERRORLEVEL值。
defrag,mem,end[D,M,E]?
 D->ErrorLevel=1
    M->ErrorLevel=2
       E->ErrotLevel=3
  • 2.默认选项与操守实践参数设置示例
代码语言:javascript复制
# 不区分大小写选项
CHOICE /C YNC /CS /M "确认请按 Y,否请按 N,或者取消请按 C。"
CHOICE /C ab /CS /M "选项 1 请选择 a,选项 2 请选择 b。"

# 不显示选项参数
CHOICE /C ab /N /M "选项 1 请选择 a,选项 2 请选择 b。"

# 若10s后还没选择输入,则默认值为y。
CHOICE /T 10 /C ync /CS /D y

0x03 批处理脚本进阶命令

setlocal 命令 - 设置脚本局部环境

描述: 此命令用于设置批处理文件中环境改动的本地化操作,在执行 SETLOCAL 之后所做的环境改动只限于批处理文件,若要还原原先的设置必须执行 ENDLOCAL。

语法参数:

代码语言:javascript复制
setlocal {enableextension | disableextensions} {enabledelayedexpansion | disabledelayedexpansion}

# 命令参数:
enableextension | disableextensions : 启用或禁用命令处理器扩展此参数比 CMD /E:ON 或 /E:OFF开关有优先权
enabledelayedexpansion | disabledelayedexpansion :启用或禁用延缓环境变量赋值扩展此参数比 CMD /V:ON 或 /V:OFF 开关有优先权

示例演示:

  • 1.验证当前批处理是否支持命令扩展。
代码语言:javascript复制
@echo off
@REM 具有不正确参数的 VERIFY 命令将 ERRORLEVEL 值初始化成非零值
@REM 指示 cmd.exe 是否要验证文件是否已正确地写入磁盘,此处输入错误参数
VERIFY OTHER 2>null
echo %ERRORLEVEL%
@REM 启用扩展
SETLOCAL ENABLEEXTENSIONS
echo %ERRORLEVEL%
@REM 验证是否启用扩展
IF ERRORLEVEL 0 echo enable extensions
IF ERRORLEVEL 1 echo Unable to enable extensions

执行结果:

代码语言:javascript复制
$ 01.setlocal.bat
1
0
enable extensions

温馨提示:具有不正确参数的 VERIFY 命令将 ERRORLEVEL 值初始化成非零值,从上述结果也可看出。

温馨提示:若未指定ENDLOCAL命令,则当到达批处理文件结尾时,对于该批处理文件的每个尚未执行的 SETLOCAL 命令,都会有一个隐含的 ENDLOCAL 被执行。

  • 2.示例演示2命令扩展验证。
代码语言:javascript复制
@echo off
:: # 启用命令扩展
setlocal enableExtensions

:: # 当前脚本执行环境是否支持扩展以及输出 CMDEXTVERSION 值
echo  "命令扩展是否启用:" %CMDEXTVERSION%

:: # 查看用户是否定义了CMDEXTVERSION环境变量
set | findstr "CMDEXTVERSION">nul
if ERRORLEVEL 1 (
:: # 如果%CMDEXTVERSION%非空,则当前CMD.EXE开启了命令扩展,否则禁用
if ""=="%CMDEXTVERSION%"  ( echo 命令扩展被禁用) else ( echo 命令扩展被开启)
REM # 检查当前命令解释器的版本
if "%CMDEXTVERSION%"=="2" (
    echo 当前命令解释器版本为 2
    REM 在这里执行与版本 2 相关的操作
) else (
    echo 当前命令解释器版本不是 2
    REM 在这里执行与其他版本相关的操作
)

IF CMDEXTVERSION 0 (echo "True -> %CMDEXTVERSION%") ELSE (echo "False -> %CMDEXTVERSION%") # "True -> 2"
IF CMDEXTVERSION 1 (echo "True -> %CMDEXTVERSION%") ELSE (echo "False -> %CMDEXTVERSION%") # "True -> 2"
IF CMDEXTVERSION 2 (echo "True -> %CMDEXTVERSION%") ELSE (echo "False -> %CMDEXTVERSION%") # "True -> 2"
IF CMDEXTVERSION 3 (echo "True -> %CMDEXTVERSION%") ELSE (echo "False -> %CMDEXTVERSION%") # "False -> 2"
IF CMDEXTVERSION 4 (echo "True -> %CMDEXTVERSION%") ELSE (echo "False -> %CMDEXTVERSION%") # "False -> 2"

:: # 禁用命令扩展
setlocal disableExtensions
echo %CMDEXTVERSION%

endocal 命令 - 终止脚本局部环境

描述: 此命令主要用于结束批处理文件中环境改动的本地化操作,在执行 ENDLOCAL 之后所做的环境改动不再仅限于批处理文件,批处理文件结束后原先的设置将无法还原。

若 SETLOCAL 使用 ENABLEEXTENSIONS 或DISABLEEXTENSIONS 选项启用或停用了命令扩展,那么在ENDLOCAL 之后,命令扩展的启用/停用状态会还原到执行相应的 SETLOCAL 命令前的状态。

示例演示:

代码语言:javascript复制
@echo off
@REM 设置 Setlocal 之前
echo Before Setlocal:
set PATH
pause

@REM 开启局部环境变量
setlocal  

@REM 重置PATH环境变量,只会在 setlocal ~ endlocal 命令之间的代码块生效。
@REM reset environment var PATH
set PATH=E:TOOLS
echo after Setlocal and reset PATH
set PATH
Pause

@REM 结束局部环境变量的改变,恢复原装
endlocal   

@REM 验证环境变量是否被修改
echo Recovery PATH by Endlocal
Set PATH

脚本解释: 从上例我们可以看到环境变量PATH第1次被显示得时候是系统默认路径, 被设置成了“E:TOOLS”后显示为“E:TOOLS,但当 Endlocal 后我们可以看到他又被还原成了系统的默认路径, 但这个设置只在该批处理运行的时候有作用, 当批处理运行完成后环境变量PATH将会还原。

总结: 无论在 Setlocal 命令之前它们的设置是什么,这些修改会一直保留到匹配的 Endlocal 命令。

doskey 命令 - 创建脚本宏命令别名

描述: 此命令类似于Linux中的alias命令,它允许您创建、编辑和使用自定义命令别名, 在经常需要输入重复命令的场景下有非常大的用处。

语法参数:

代码语言:javascript复制
DOSKEY [/REINSTALL] [/LISTSIZE=size] [/MACROS[:ALL | :exename]] [/HISTORY] [/INSERT | /OVERSTRIKE] [/EXENAME=exename] [/MACROFILE=filename] [macroname=[text]]

# 参数说明
/REINSTALL         # 安装新的 Doskey 副本

/MACROS            # 显示所有 Doskey 宏
/MACROS:ALL        # 为具有 Doskey 宏的所有可执行文件显示所有 Doskey 宏
/MACROS:exename    # 显示指定可执行文件的所有 Doskey 宏

/LISTSIZE=size     # 设置命令历史记录的缓冲区大小
/HISTORY           # 显示存储在内存中的所有命令

/INSERT             # 指定您键入的新文本插入到旧文本中
/OVERSTRIKE         # 指定新文本覆盖旧文本

/EXENAME=exename    # 指定可执行文件
/MACROFILE=filename # 指定要安装的宏文件
macroname           # 指定您创建的宏的名称,例如 ls
text                # 指定要录制的命令,例如 dir $*

以下是 doskey 宏预定义的一些特殊代码: 上下箭头重新调用命令;Esc 清除命令行;F7显示命令历史记录;Alt F7 清除命令历史记录;F8 搜索命令历史记录;F9 按编号选择命令;Alt F10 清除宏定义

代码语言:javascript复制
$T       #命令分隔符允许一个宏中存在多个命令,等同于 &&
$1-$9    # 批处理参数与批处理程序中的 %1-%9 等同于 Linux 中的位置参数。
$*       # 以命令行中命令名称后面的任何内容替换的符号所有参数

示例演示:

  • 1.使用doskey快速创建命令别名,例如在windows批处理中实现ls命令显示目录文件。
代码语言:javascript复制
@REM 自定义宏命令,意思是执行dir /w /p  
@REM 方式1
doskey ls=dir /w /p  

@REM 方式2
echo ll=dir /p /b > AliasCommand.txt
doskey /macrofile=AliasCommand.txt

执行结果:

  • 2.显示使用doskey设置的别名。
代码语言:javascript复制
@REM 显示别名
doskey alias=doskey /macros:all 

@REM 导出导入别名
doskey /macros:all >> my.alias
doskey /macrofile=my.alias

执行结果:

代码语言:javascript复制
$ alias
[cmd.exe]
  ls=dir /w /p
  ll=dir /p /b
  alias=doskey /macros:all
  • 3.显示使用doskey进行交互式的命令录制,并使用预制快捷键进行调用执行,例如按下F7将显示如下界面。
代码语言:javascript复制
$  doskey
$  whoami
weiyigeekweiyigeek
$  net user
$  date /t; time /t
2023-07-20
$  time /t
12:40

@REM 查看命令执行历史,类似于Linux中的history
doskey /HISTORY
@REM 设置命令历史记录的缓冲区大小类似于Linux中的HISTSIZE环境变量
doskey /LISTSIZE=128 
  • 3.对于喜欢使用Linux的开发者,常常习惯于执行ls或者cd命令,我们可以尝试进行设置别名以适应习惯。
代码语言:javascript复制
@echo off
doskey cd = @echo off $T cd /d $* $T echo on
doskey ls = dir $*
doskey ps = tasklist
  • 4.此时如果你是一名网络安全人员,你会发现Doskey妙用不止于此,还可以做后门留存使用(针对持续权限还是很有帮助的)。
代码语言:javascript复制
@REM 举个例子实现后门脚本的执行。
echo title �% ^&^& calc.exe >> cmd_title.bat

@REM 执行cd时执行我们自定义的后门脚本,当执行cd后将会触发执行calc命令,下述的 $T 等同于 &&
doskey cd = echo off $T cd /d $* $T  $T set od=�% $T "cmd_title.bat" $T echo on 

# 温馨提示: 此处使用 echo off 、echo on 是微课宏在运行时不会多次换行。

知识扩展: 值得注意的时,Windows 上的Doskey貌似比Linux下的alias更为强大,由于其支持接受参数的功能,而Linux中若需要使用参数必要使用function来进行实现,但是同样是采用1.. 2..

本文至此完毕,更多技术文章,尽情等待下篇好文!

原文地址: https://cloud.tencent.com/developer/article/2129350

1 人点赞