bat脚本:快速入门

时间:2024-11-13 08:44:15

bat脚本全称batch脚本,也称批处理文件,是Windows系统默认支持的脚本语言。本文主要介绍windows bat脚本的基础语法以及一些常用功能的实现,通过这些基础操作的组合可以编写出强大的脚本工具。

目录

  • 1. 常用命令介绍
    • 1.0 /? 获取命令帮助说明
      • 1.1 echo和@
    • 1.2 rem和::
    • 1.3 call和start
      • 1.3.1 call使用场景
        • 1.3.1.1 调用脚本
        • 1.3.1.2 调用命令行字符串
        • 1.3.1.3 调用带返回值的子程序
        • 1.3.1.4 变量嵌套与命令嵌套(待完善)
      • 1.3.2 start使用场景
    • 1.4 pause
    • 1.5 errorlevel
    • 1.6 goto和:
    • 1.7 if条件
    • 1.8 for循环
      • 1.8.1 FOR循环的4个参数 `/d` `/l` `/r` `/f`
        • 1.8.1.1 参数 `/d`
        • 1.8.1.2 参数 `/l`
        • 1.8.1.3 参数 `/r`
        • 1.8.1.4 参数 `/f`
      • 1.8.2 FOR循环中的变量
        • 1.8.2.1 变量 `~I`,删除首尾引号("),扩展 %I
        • 1.8.2.2 变量 `%~fI`,将 %I 扩展到一个完全合格的路径名
        • 1.8.2.3 变量 `%~dI`,仅将 %I 扩展到一个驱动器号
        • 1.8.2.4 变量 `%~pI`,仅将 %I 扩展到一个路径
        • 1.8.2.5 变量 `%~nI`,仅将 %I 扩展到一个文件名
        • 1.8.2.6 变量 `%~xI`,仅将 %I 扩展到一个文件扩展名
        • 1.8.2.7 变量 `%~sI`,扩展的路径只含有短名
        • 1.8.2.8 变量 `%~aI`,将 %I 扩展到文件的文件属性
        • 1.8.2.9 变量 `%~tI`,将 %I 扩展到文件的日期/时间
        • 1.8.2.10 变量 `%~zI`,将 %I 扩展到文件的大小
        • 1.8.2.11 变量 `%~$PATH:I`,查找列在路径环境变量的目录,并将 %I 扩展到找到的第一个完全合格的名称
    • 1.9 setlocal 与 变量延迟
    • 1.10 常用符号
      • 1.10.1 `%` 批处理变量引导符
      • 1.10.2 `>` 重定向符
      • 1.10.3 `|` 命令管道符
      • 1.10.4 `^` 转义字符
      • 1.10.5 `&`、`&&`、`||` 命令组合
      • 1.10.6 `,`和`;`的区别
      • 1.10.7 % `!`变量延迟引用
      • 1.10.8 数学运算符
    • 1.11 时间处理
      • 1.11.1 date和time
      • 1.11.2 时间延迟
        • 1.11.2.1 利用ping命令
        • 1.11.2.2 利用for循环
        • 1.11.2.3 利用vbs延迟函数
        • 1.11.2.4 利用goto循环
        • 1.11.2.5 利用timeout函数
      • 1.11.3 一个定时任务模版
      • 1.11.4 系统定制任务
    • 1.12 字符串处理
      • 1.12.1 中文乱码
      • 1.12.2 字符串截取
      • 1.12.3 字符串局部替换
      • 1.12.3 字符串拼接
    • 1.13 网络管理
      • 1.13.1 ping网络嗅探
      • 1.13.2 netstat网络查看
      • 1.13.3 tracert路由跟踪
    • 1.14 其他命令
      • 1.14.1 cls清空屏幕
      • 1.14.2 random随机数
      • 1.14.3 type显示文本文件内容
      • 1.14.4 where搜索文件所在的目录
      • 1.14.5 tasklist&taskkill进程管理
  • 2. 文件操作
    • 2.1 文件(夹)创建
    • 2.2 文件(夹)删除
    • 2.3 文件(夹)重命名
    • 2.4 文件拷贝和移动
    • 2.5 文件(夹)查找
      • 2.5.1 dir打印指定目录下的文件列表
      • 2.5.2 tree以树状结构打印指定目录下的文件列表
    • 2.5 文件内容查找
      • 2.5.1 find
    • 2.6 文件目录切换
  • 3. 界面相关
    • 3.1 title修改命令行窗口标题
    • 3.2 color修改命令行背景色、前景色
    • 3.3 修改命令行宽高
    • 3.4 设计一个用户菜单界面
    • 3.5 实现进度条
  • 4. 变量
    • 4.1 系统变量
    • 4.2 环境变量
    • 4.3 批处理入参变量
    • 4.4 自定义变量
    • 4.5 设置网络代理
  • 5. 调用三方应用程序
    • 5.1 调用ftp
    • 5.2 调用7-zip
    • 5.3 调用VBScript程序
    • 5.4 调用jar包
    • 5.5 调用exe程序
  • 6. 转换为可执行文件
    • 6.1 转换成.com文件
    • 6.2 转换成.exe文件
  • 7. 参考资料

1. 常用命令介绍

1.0 /? 获取命令帮助说明

格式:command /?

注意:

  • Windows 命令行不区分大小写
  • Ctrl+C组合键来强行终止运行脚本

1.1 echo和@

  • echo
    1. 回显命令内容
      格式:echo [你的文字]
      在命令行窗口会打印命令内容
    2. 打开或关闭回显功能
      格式:echo [{ on|off }]
    3. 输出空行
      格式:echo. 或echo, 或echo: [>文件]
      相当于输入一个回车。可以作为其它命令的输入,比如echo.|time即相当于在TIME命令执行后给出一个回车。所以执行时系统会在显示当前时间后,自动返回到DOS提示符状态
    4. 答复命令中的提问
      比如:C:>ECHO Y|DEL A :.,相当于执行DEL A :*.*命令时,系统确认框中直接返回Y,从而执行下一步,免去手动确认的过程
    5. 建立新文件或增加文件内容
      格式:ECHO >文件名或ECHO 文件内容>>文件名;
    6. 使喇叭鸣响
      格式:ECHO ^G
      ^G是在dos窗口中用Ctrl+G或Alt+007输入,输入多个^G可以产生多声鸣响
  • @:表示本条命令不回显,仅在本条命令生效,优先级高于echo off;

示例:

:: ===基础使用===
:: 一般脚本执行时不需要打印每条命令的具体内容,所以推荐在脚本起始位置就设置关闭全局echo,需要显示信息时使用echo命令打印提示信息
@echo off
echo hello world
:: 开启全局echo回显
@echo on

:: ===高阶用法===
::  使用echo创建文件
echo>
::  使用echo为文件写数据,会覆盖
echo ::我是第1行>
::  使用echo为文件追加内容,不覆盖
echo ::我是第2行>>
:: 输出换行符(空行)
echo. >>
:: 输出
call 
:: type表示打印文件内容到窗口
type 

1.2 rem和::

  • rem:注释,支持echo回显;
  • :::注释,不支持echo回显,不能在()语句块中使用。

扩展:冒号后紧跟一个非字母数字的一个特殊符号其实都等价于双冒号,目的是使goto无法识别;

示例

@echo on
rem 这是注释内容,由于指定了echo on,命令行会打印这段注释
:: 这也是注释内容,但是不支持回显
@echo off

1.3 call和start

  • call:调用另一个批处理文件,如果不用call而直接调用别的批处理文件,那么执行完那个批处理文件后将无法返回当前文件并执行当前文件的后续命令;
  • start:批处理中调用外部程序的命令(该外部程序在新窗口中运行,批处理程序继续往下执行,不理会外部程序的运行状况),如果直接运行外部程序则必须等外部程序完成后才继续执行剩下的指令

1.3.1 call使用场景

1.3.1.1 调用脚本
:: 调用另一个脚本,并在执行结束后返回本脚本
:: filename 参数必须具有 .bat 或 .cmd 扩展名
call  参数1 参数2
1.3.1.2 调用命令行字符串
:: 如果不用call,而直接运行%cmdstr%,将显示结果%aa%,而不是123456
set aa=123456
set cmdstr=echo %aa%
call %cmdstr%
pause
1.3.1.3 调用带返回值的子程序

这里重点关注getSum中shift的用法,默认右移1位,即shift等价于shift /1。
以本demo为例:%1在没有右移时表示第一个入参,在shift /1之后,%1指向的是原%2的入参。

@echo off
rem 调用getString子程序
call :getString return
echo return = %return%
pause


@echo off
set sum=0
call :getSum 1 2 3 4 5
echo sum = %sum%
pause
goto :eof


rem 利用入参实现返回值
:getString
set %1=from sub script
goto :eof

rem 利用全局变量实现返回值
:getSum
set /a sum+=%1
shift /1
if not "%1"=="" goto getSum
goto :eof
1.3.1.4 变量嵌套与命令嵌套(待完善)

比如设变量word为“abcdefghij”,变量num为“123456789”
%word:~4,1%为e,其中4可以从变量num中取值,即%num:~3,1%,写成组合形式如下:
%word:~%num:~3,1%,1% 经测试这种写法不能正确执行,写成%word:~(%num:~3,1%),1%同样不行,那么,怎么实现这种变量嵌套呢?这就必须结合命令嵌套。

什么是命令嵌套呢?简单的说,首先用一条dos命令生成一个字符串,而这个字符串是另一条dos命令,用call语句调用字符串将其执行,从而得到最终结果。

示例:

@echo off
set word=abcdefghij
set num=123456789
echo %word:~%num:~2,1%,1%

1.3.2 start使用场景

start命令示例:

:: 调用文件管理器打开D盘
start explorer d:\
:: 打开命令行窗口
start cmd

1.4 pause

暂停并运行显示:请按任意键继续. . .
要显示其他提示语,可以这样用:Echo 其他提示语 & pause > nul

1.5 errorlevel

程序返回码,格式:echo %errorlevel%。
每个命令运行结束,可以用这个命令行格式查看返回码,用于判断刚才的命令是否执行成功,成功为0(默认值),失败为1。

:: 调用脚本并打印执行结果
call  & echo %errorlevel%

1.6 goto和:

在批处理中允许以“:XXX”来构建一个标号,然后用GOTO XXX跳转到标号:XXX处,然后执行标号后的命令。执行逻辑有点类似于do…while,使用goto可以实现比for语句更复杂的循环逻辑。
示例:

@echo off
:: 打印1234
:start
set /a var+=1
echo var = %var%
if %var% leq 3 goto start
pause

1.7 if条件

语法格式:

  • IF [NOT] ERRORLEVEL number command
  • IF [NOT] string1==string2 command
  • IF [NOT] EXIST filename command

增强用法:IF [/I] string1 compare-op string2 command

  • [/I] 加上/I就不区分大小写了!
  • EQU - 等于
  • NEQ - 不等于
  • LSS - 小于
  • LEQ - 小于或等于
  • GTR - 大于
  • GEQ - 大于或等于

示例:配合else使用:

IF EXIST filename (
del filename
) ELSE (
echo filename missing
)

示例:if else if else嵌套

@echo off
rem 可读性好,兼容性好

setlocal EnableDelayedExpansion
set option=2
set sum=-1

if %option% == 3 ( 
  echo three 
  set /a sum=%option%*%option%*%option%
) ^
else if %option% == 2 ( 
  echo two 
  if not %sum% equ -1 set /a sum=2*%option%
) ^
else if %option% == 1 ( 
  echo one 
  set /a sum=%option% 
) ^
else ( 
  echo zero 
  set /a sum=0 
)

echo sum = !sum!

pause

示例:根据上一个命令执行结果确定下一步命令

@echo off
dir c:
:: 退出代码为>=1就跳至标题1处执行,>=0就跳至标题0处执行
IF ERRORLEVEL 1 goto 1
IF ERRORLEVEL 0 goto 0
:: 上面的两行不可交换位置,否则失败了也显示成功。
:0
echo 命令执行成功!
:: 程序执行完毕跳至标题exit处退出
goto exit
:1
echo 命令执行失败!
:: 程序执行完毕跳至标题exit处退出
goto exit
:exit
pause

示例:文件是否存在

echo off
IF EXIST  echo 文件存在!
IF not EXIST  echo 文件不存在!

1.8 for循环

基本格式:FOR %%variable IN (set) DO command [command-parameters]

  • %%variable 指定一个单一字母表示可替换的参数。
  • (set) 指定一个或一组文件名,可以使用通配符。
  • command 指定对每个文件执行的命令。
  • command-parameters为特定命令指定参数或命令行开关。

1.8.1 FOR循环的4个参数 /d /l /r /f

1.8.1.1 参数 /d

使用格式:FOR /D %%variable IN (set) DO command [command-parameters]
作用:指定遍历范围为当前目录,且遍历对象仅为文件夹不包含文件类型

如果 set 中包含通配符(* 和 ?),将对与 set 相匹配的每个目录(而不是指定目录中的文件组)执行指定的 Command。这个参数主要用于目录搜索,不会搜索文件

# 打印c盘根目录所有文件夹名称
@echo off
for /d %%i in (c:\*) do echo %%i
pause

# 打印c盘根目录名字只有1-3个字母的文件夹
for /d %%i in (c:\???) echo %%i
pause
1.8.1.2 参数 /l

使用格式:FOR /L %%variable IN (start,step,end) DO command [command-parameters]
作用:明确循环次数和步长

表示以增量形式从开始到结束的一个数字序列。比如:(1,1,5) 将产生序列 1 2 3 4 5,(5,-1,1) 将产生序列 (5 4 3 2 1)。

1.8.1.3 参数 /r

使用格式:FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
作用:指定递归遍历范围为/r后面的路径,遍历对象含文件和文件夹

检查以 [drive:]path 为根的目录树,指向每个目录中的FOR 语句。如果在 /R 后没有指定目录,则使用当前目录。如果集仅为一个单点(.)字符或则具体的文件名(不含通配符),则忽略set枚举该目录树。

@echo off
:: 递归遍历指定路径
for /r e: %%i in (*.exe) do echo %%i
:: 递归遍历当前路径
for /r %%i in (*.exe) do echo %%i
pause
1.8.1.4 参数 /f

逐行遍历文本文件、文本、命令行中的字符串

使用格式:
FOR /F [“options”] %%variable IN (file-set) DO command [command-parameters]
FOR /F [“options”] %%variable IN (“string”) DO command [command-parameters]
FOR /F [“options”] %%variable IN (‘command’) DO command [command-parameters]
作用:遍历读取文件、字符串、命令行中指定内容执行相应操作

其中, [“options”]为一个或多个解析选项,选项之间用空格断开,这些解析选项包括:

  • eol=c - 指一个行注释字符的结尾(就一个)(备注:默认以使用;号为行首字符的为注释行)
  • skip=n - 指在文件开始时忽略的行数,(备注:最小为1,n可以大于文件的总行数,默认为1。)
  • delims=xxx - 指分隔符集。这个替换了空格和跳格键的默认分隔符集。
  • tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代的 for 本身。m-n格式为一个范围。

非常抽象,直接看示例:

@echo off
rem 首先建立临时文件
echo ;注释行,这是临时文件,用完删除 >
echo 11段 12段 13段 14段 15段 16段 >>
echo 21段,22段,23段,24段,25段,26段 >>
echo 31段-32段-33段-34段-35段-36段 >>
FOR /F "eol=; tokens=1,3* delims=,- " %%i in () do echo %%i %%j %%k
Pause
Del 

运行显示结果:

11段 13段 14段 15段 16段
21段 23段 24段,25段,26段
31段 33段 34段-35段-36段
请按任意键继续. . .

解析:
eol=; 分号开头的行为注释行
tokens=1,3* 将每行第1段,第3段和剩余字段分别赋予变量%%i,%%j,%%k
delims=,- (减号后有一空格)以逗号减号和空格为分隔符,空格必须放在最后

再看一个command的示例:

@echo off
FOR /F "delims=" %%i in ('net user') do @echo %%i
pause

运行结果:
本机全部帐号名字就出来了

解析:
把扩号内的内容用两个单引号引起来就表示那个当命令执行,FOR会返回命令的每行结果,加那个"delims=" 是为了让我空格的行能整行显示出来,不加就只显示空格左边一列!

1.8.2 FOR循环中的变量

1.8.2.1 变量 ~I,删除首尾引号("),扩展 %I

示例:

@echo off
echo ^"1111>
echo "2222">>
echo 3333^">>
echo "4444"44>>
echo ^"55"55"55>>

rem 上面建立临时文件,注意不成对的引号要加转义字符^,重定向符号前不要留空格
FOR /F "delims=" %%i IN () DO echo %%~i
pause
del 

执行结果:
1111 #字符串前的引号被删除了
2222 #字符串首尾的引号都被删除了
3333" #字符串前无引号,后面的引号保留
4444"44 #字符串前面的引号删除了,而中间的引号保留
55"55"55 #字符串前面的引号删除了,而中间的引号保留

总结规律:
无头不删,有头连尾删,中间不删

1.8.2.2 变量 %~fI,将 %I 扩展到一个完全合格的路径名

示例:

@echo off
# 打印当前目录下所有文件的绝对路径
for /f %%i in ('dir /b') do echo %%~fi
# 打印当前目录下所有文件的文件名
:: for /f %%i in ('dir /b') do echo %%i

执行结果:
C:\Documents and Settings\Administrator\桌面\
C:\Documents and Settings\Administrator\桌面\

1.8.2.3 变量 %~dI,仅将 %I 扩展到一个驱动器号

示例:

FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~di
pause

执行结果:
C:
C:

1.8.2.4 变量 %~pI,仅将 %I 扩展到一个路径

注意:所谓的路径就是文件所在目录,及parent的绝对路径,注意与%%~fI区别

1.8.2.5 变量 %~nI,仅将 %I 扩展到一个文件名

示例:

# 只打印文件名(不含拓展名)
for /f %%i in ('dir /b') do echo %%~ni

# 打印文件名(含拓展名)
for /f %%i in ('dir /b') do echo %%i
1.8.2.6 变量 %~xI,仅将 %I 扩展到一个文件扩展名

只打印文件拓展名

1.8.2.7 变量 %~sI,扩展的路径只含有短名

好像跟%%~fI效果一样

1.8.2.8 变量 %~aI,将 %I 扩展到文件的文件属性

打印出来的东西,应该是读写权限之类的:
–a--------

1.8.2.9 变量 %~tI,将 %I 扩展到文件的日期/时间

打印文件日期

1.8.2.10 变量 %~zI,将 %I 扩展到文件的大小

打印文件大小

1.8.2.11 变量 %~$PATH:I,查找列在路径环境变量的目录,并将 %I 扩展到找到的第一个完全合格的名称

如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串

# 在PATH变量里指定的路径里搜索文件,如果有则会把他所在绝对路径打印出来,没有就打印一个错误!
@echo off
FOR /F "delims=" %%i IN (“”) DO echo %%~$PATH:i
pause

执行结果:
C:\WINDOWS\system32\

1.9 setlocal 与 变量延迟

现象:

@echo off
set a=4
set a=5 & echo %a%
pause

结果:4
解说:批处理读取命令时是按行读取的(另外例如for命令等,其后用一对圆括号闭合的所有语句也当作一行),在处理之前要完成必要的预处理工作,这其中就包括对该 行命令中的变量赋值。我们现在分析一下例1,批处理在运行到这句“set a=5 & echo %a%”之前,先把这一句整句读取并做了预处理——对变量a赋了值,那么%a%当然就是4了!(没有为什么,批处理就是这样做的。)

@echo off
setlocal enabledelayedexpansion
set a=4
set a=5 & echo !a!
pause 

结果:5

@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,5) do (
set a=%%i
echo !a!
)
pause

结果:

1
2
3
4
5

例:交换两个变量的值,且不用中间变量

@echo off
::目的:交换两个变量的值,但是不使用临时变量
::Code by JM 2007-1-24 [email=CMD@XP]CMD@XP[/email]
::出处:/forum/?tid=27078
set var1=abc
set var2=123
echo 交换前: var1=%var1% var2=%var2%
set var1=%var2%& set var2=%var1%
echo 交换后: var1=%var1% var2=%var2%
pause

1.10 常用符号

1.10.1 % 批处理变量引导符

引用变量用%var%,调用程序外部参数用%1至%9等等

  • %0 批处理文件本身,包括完整的路径和扩展名,可以调用批处理自身,以达到批处理本身循环的目的,也可以复制文件自身等等
  • %1 第一个参数
  • %9 第九个参数
  • %* 从第一个参数开始的所有参数
:: 最简单的复制文件自身的方法
copy %0 d:\

1.10.2 > 重定向符

DOS的标准输入输出通常是在标准设备键盘和显示器上进行的,利用重定向,可以方便地将输入输出改向磁盘文件或其它设备。

  1. 大于号>将命令发送到文件或设备,例如打印机>prn。使用大于号“>”时,有些命令输出(例如错误消息)不能重定向。
  2. 双大于号>>将命令输出添加到文件结尾而不删除文件中已有的信息。
  3. 小于号<从文件而不是键盘上获取命令所需的输入。
  4. >&符号将输出从一个默认I/O流(stdout[1],stdin[0],stderr[2])重新定向到另一个默认I/O流。
  5. <&>&相反,从一个句柄读取输入并将其写入到另一个句柄输出中
  6. 1>nul 表示禁止输出正确的信息, 2>nul 表示禁止输出错误信息。
@echo off
set /p str=<%0
echo %str%

运行显示批处理文件自身的第一行:@echo off

1.10.3 | 命令管道符

格式:第一条命令 | 第二条命令 [| 第三条命令…]
将第一条命令的结果作为第二条命令的参数来使用,记得在unix中这种方式很常见。

:: 查找C:\所有,并发现TXT字符串
dir c:\|find "txt"

1.10.4 ^ 转义字符

^是对特殊符号<,>,&的前导字符,在命令中他将以上3个符号的特殊功能去掉,仅仅只把他们当成符号而不使用他们的特殊意义。

@echo off
echo test ^>
# 结果则是:test > 

echo a^
b^
c
# 输出abc不换行

1.10.5 &&&|| 命令组合

  • &:前一个命令执行失败不影响后边的命令执行;
  • &&:前一个命令执行失败,后边的命令将不执行;
  • ||:前一个命令失败才执行后一个命令;
  • 命令的优先级:
    管道命令的优先级高于重定向命令,重定向命令的优先级高于组合命令
  • 变量延迟:
    这种多条命令被视为一条命令行时,如果其中有变量,就涉及到变量延迟的问题。
# 把C盘和D盘的文件和文件夹列出到文件中
(dir c: & dir d:)>
# 或者简写
dir c:;d:>>

1.10.6 ,;的区别

  • ,:逗号相当于空格,在某些情况下“,”可以用来当做空格使
  • ;:当命令参数相同时,可以将不同目标用;来隔离,但执行效果不变,如执行过程中发生错误,则只返回错误报告,但程序仍会执行
# 逗号当空格用
dir,c:\

# 打印多个文件目录
dir c:;d:;e:\

1.10.7 % !变量延迟引用

在变量延迟问题中,用来表示变量,即%var%应该表示为!var!,具体请看前面的setlocal命令介绍。

1.10.8 数学运算符

+,减-,乘*,除/,取模%%,这些运算符只有一种使用场景,就是在set /a命令的等号右边使用,即:set /a var=%num%*5
需要注意的是涉及到组合命令或者for循环时,注意变量的更新问题,需要结合setlocal和变量延迟。

1.11 时间处理

1.11.1 date和time

  • date:显示和设置当前日期
  • time:显示和设置当前时间
::  从文件中读入命令输入,而不是从键盘中读入
@echo off
echo date>
date<
del 

1.11.2 时间延迟

1.11.2.1 利用ping命令

实测效果:每个任务ping3次,任务耗时均稳定在2秒多一点点

@echo off
:usePing
echo befor:%date%-%time%
REM /n 3表示ping 3次
REM >nul就是屏蔽掉ping命令所打印的内容
ping /n 3 127.0.0.1 >nul
echo after:%date%-%time%
echo click to resume next & pause>nul
goto usePing
1.11.2.2 利用for循环

实测效果:循环5000次耗时1s不到,不推荐

@echo off
echo 延时前:%time%
for /l %%i in (1,1,5000) do echo %%i>nul
echo 延时后:%time%
pause
1.11.2.3 利用vbs延迟函数

实测效果:精确度毫秒,误差1000毫秒内

@echo off
echo 延时前:%time%
call :delay 5000
echo 延时后:%time%
goto :eof

:delay
echo  %1>
CScript //b 
del 
goto :eof
1.11.2.4 利用goto循环

使用效果:精确度10毫秒,误差50毫秒内

@echo off
echo 程序开始时间:%Time%
call :delay 10
echo 实际延迟时间:%totaltime%毫秒
echo 程序结束时间:%time%
pause
exit

::-----------以下为延时子程序--------------------
:delay
@echo off
if "%1"=="" goto :eof
set DelayTime=%1
set TotalTime=0
set NowTime=%time%
::读取起始时间,时间格式为:13:01:05.95
:delay_continue
set /a minute1=1%NowTime:~3,2%-100
set /a second1=1%NowTime:~-5,2%%NowTime:~-2%0-100000
set NowTime=%time%
set /a minute2=1%NowTime:~3,2%-100
set /a second2=1%NowTime:~-5,2%%NowTime:~-2%0-100000
set /a TotalTime+=(%minute2%-%minute1%+60)%%60*60000+%second2%-%second1%
if %TotalTime% lss %DelayTime% goto delay_continue
goto :eof
1.11.2.5 利用timeout函数

格式:TIMEOUT [/T] timeout [/NOBREAK]

:: 延时5s,并禁用失败信息
timeout /t 5 /nobreak 2>nul

1.11.3 一个定时任务模版

设计思路:使用goto实现循环逻辑,使用一种时间延迟方案实现轮询时间间隔

@echo off
set MAX_LOOP_COUNT=5
set SLEEP=1000
set loop_count=0

:loop
echo loop%loop_count% start at: %time%
call :task
call :delay %SLEEP% %loop_count%
echo loop%loop_count% end at: %time%
set /a loop_count+=1
if /i %loop_count% gtr %MAX_LOOP_COUNT% (
goto :eof 
) else (
goto loop
)

:delay
if not exist  echo  %1>
cscript //B 
if "%2"=="%MAX_LOOP_COUNT%" del 
goto :eof

:task
rem 这里是实际耗时任务
echo 模拟耗时任务
goto :eof

1.11.4 系统定制任务

使用GUI设置界面,这里不做详细介绍,参考:windows中怎么添加定时任务

1.12 字符串处理

1.12.1 中文乱码

cmd的默认字符编码为ANSI且不可更改,而一般文本编辑器默认的字符编码是UTF-8,因此中文乱码很常见,解决办法是切换bat脚本的字符编码格式为ANSI或GB2312即可

1.12.2 字符串截取

使用格式:%str:~start,count%

示例:

@echo off
set str=hello world
echo 原字符串为:%str%
echo 截取前5个字符:%str:~0,5%
echo 截取最后5个字符:%str:~-5%
echo 截取第一个到倒数第6个字符:%str:~-1,-5%
echo 从第4个字符开始截取5个字符:%str:~3,5%
echo 从倒数第6个字符开始截取5个字符:%str:~-6,5%

1.12.3 字符串局部替换

使用格式:%str:old=new%

示例:

 @echo off
set str=hello world
echo 替换前:%str%
echo 替换后:%str:world=bat%
echo str=%str%
echo %str%
set str=%str:world=bat%
echo str=%str%

1.12.3 字符串拼接

使用格式:%str1%%str2%

示例:

@echo off
set str1=hello
set str2=world
set str1=%str1%%str2%
echo str1=%str1% str2=%str2%
pause

1.13 网络管理

1.13.1 ping网络嗅探

使用格式:ping [options] host

示例:基本用法

rem 嗅探一个域名,/n 3表示指定嗅探次数为3次
ping /n 3 
rem 嗅探一个IP(不支持端口,加端口可以使用telnet)
ping 10.10.80.110

示例:嗅探一个未被占用的局域网IP

@echo off
set /p seg1=请输入网段的前三位数字以 . 结尾,比如10.10.80.:
set /a seg2=1

:start
set ip=%seg1%%seg2%
echo try ip = %ip%
ping ip -w 1 -n 1|find /i "Lost = 1"&&set c=1||set c=0
if not %c%==0 set seg2+=1 & if seg2==255 goto fail else goto start
echo 可用的IP为:%ip% & pause>nul
goto :eof

:fail
echo 无可用IP
pause

1.13.2 netstat网络查看

命令行查看端口占用并关闭进程

# 查找8080端口使用情况,此命令会列出相关进程信息,然后结合taskkill即可
netstat -aon|findstr "8080" 

1.13.3 tracert路由跟踪

Usage: tracert [-d] [-h maximum_hops] [-j host-list] [-w timeout]
               [-R] [-S srcaddr] [-4] [-6] target_name

Options:
    -d                 不处理主机名.
    -h maximum_hops    Maximum number of hops to search for target.
    -j host-list       Loose source route along host-list (IPv4-only).
    -w timeout         每个ICMP包的等待超时时间.
    -R                 Trace round-trip path (IPv6-only).
    -S srcaddr         Source address to use (IPv6-only).
    -4                 强制IPv4.
    -6                 强制IPv6.
    -target_name  目标IP或者域名

示例:

# 跟踪百度路由信息
trace -d 

# 根据指定IP
trace -d 192.168.1.100

1.14 其他命令

1.14.1 cls清空屏幕

1.14.2 random随机数

%RANDOM% 系统变量 返回 0 到 32767 (215-1)之间的任意十进制数字。由 生成。

示例:获取4-12范围的随机数

@REM 产生10个[4,12]间的随机数 
@echo off 
REM 启用延迟环境变量扩展 
setlocal enabledelayedexpansion 
REM 设置随机数的最小和最大值以及求模用的变量 
set min=4 
set max=12 
set /a mod=!max!-!min!+1

for /l %%i in (1,1,10) do ( 
REM 产生[min,max]之间的随机数 
set /a r=!random!%%!mod!+!min! 
echo. 
echo 随机数%%i:!r!)

示例:生成给定位数的随机密码

@echo off
call :randomPassword 6 pass1 pass2 pass3
echo %pass1% %pass2% %pass3%
pause
exit

:randomPassword
::---------生成随机密码
::---------%1为密码长度,%2及以后为返回变量名称
::---------goto循环、变量嵌套、命令嵌套
@echo off
if "%1"=="" goto :eof
if %1 lss 1 goto :eof
set password_len=%1
set return=
set wordset=abcdefghijklmnopqrstuvwxyz023456789_
::---------------------------循环
:randomPassword1
set /a numof=%random%%%36 ::---生成0-35之间的随即数
call set return=%return%%%wordset:~%numof%,1%% ::---在wordset变量中,从的随即生成的0-35的下一个取出一个字符
set /a password_len-=1
if %password_len% gtr 0 goto randomPassword1
::---------------------------循环
if not "%2"=="" set %2=%return%
shift /2
if not "%2"=="" goto randomPassword
goto :eof

1.14.3 type显示文本文件内容

格式:TYPE [drive:][path]filename

type 1.txt

1.14.4 where搜索文件所在的目录

格式:WHERE [/R dir] [/Q] [/F] [/T] pattern…,其中pattern为正则表达式

  • 示例一:查看程序所在目录
:: 显示git所在的路径
where git

执行结果:C:\Program Files\Git\cmd\

  • 示例二:文件查找
::查找c:\windows路径下所有dll文件(不含子目录)
where c:\windows:*.dll
::查找环境变量windir目录下所有含.号的文件
where $windir:*.*
::查找c:\windows及其子目录下所有dll和exe文件
where /r c:\windows *.dll *.exe

1.14.5 tasklist&taskkill进程管理

tasklist|findstr pname
# 指定进程名称
taskkill /f /im pname
# 指定进程ID(可指定多个)
taskkill /f /pid 2152 /pid 1284

2. 文件操作

2.1 文件(夹)创建

  • 文件创建:echo
:: 使用echo创建文件
echo>
  • 文件夹创建:md
:: 使用md创建temp和目录
md temp
md d:\myfolder

rem 使用mkdir创建任意路径的目录

2.2 文件(夹)删除

文件删除:del [/q /a /f /s] filename

#删除指定文件,不能是隐藏、系统、只读文件
del d:\       

rem 删除 d:\temp 文件夹里面的所有文件,包括隐藏、只读、系统文件,不包括子目录
del /q /a /f d:\temp\*.*

文件夹删除:rd [/s /q] dirname

  • /s:删除文件夹下所有内容
  • /q:不需要确认,直接删
@echo off
del /q/a/f d:"temp"*.*

2.3 文件(夹)重命名

2.4 文件拷贝和移动

文件拷贝:

格式:copy src dst

:: 文件复制:复制当前脚本内容到指定文件
copy %0 d:\

格式:xcopy src dst /s /e /i /y

xcopy d:\mp3 e:\mp3 /s/e/i/y

文件移动:注意move不能跨盘符分区

move d:\ c:\

2.5 文件(夹)查找

2.5.1 dir打印指定目录下的文件列表

:: 打印当前目录的文件列表
dir
:: 打印C盘文件列表,如果当前在c盘子目录中,则会打印本级目录的文件列表
dir c:
:: 查找c盘根目录下,文件名含“txt”的文件
dir c:|find "txt"

2.5.2 tree以树状结构打印指定目录下的文件列表

TREE [drive:][path] [/F] [/A]

/F 显示每个文件夹中文件的名称。
/A 使用 ASCII 字符,而不使用扩展字符。

示例:

tree c:\>c盘所有文件.txt

2.5 文件内容查找

2.5.1 find

在文件中搜索字符串。格式:FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] “string” [[drive:][path]filename[ …]]

  • /V 显示所有未包含指定字符串的行。
  • /C 仅显示包含字符串的行数。
  • /N 显示行号。
  • /I 搜索字符串时忽略大小写。
  • /OFF[LINE] 不要跳过具有脱机属性集的文件。
  • “string” 指定要搜索的文字串,
  • [drive:][path]filename,指定要搜索的文件。如果没有指定路径,FIND 将搜索键入的或者由另一命令产生的文字。

Find常和type命令结合使用:

  • 挑选包含string的行:Type [drive:][path]filename | find “string” [>tmpfile]
  • 剔除文件中包含string的行:Type [drive:][path]filename | find /v “string”
  • 显示文件行数:Type [drive:][path]filename | find /c
@echo off
:: 示例1:直接使用find命令
echo 111 >
echo 222 >>
find "111" 
del 
pause

:: 示例2:结合type命令,显示效果更友好
echo 111 >
echo 222 >>
type |find "111" 
del 
pause

2.6 文件目录切换

cd:
cd path 进入当前路径的子目录
cd /d “[drive:][path]” 进入任何指定目录
cd … 进入上级目录

pushd:保存当前目录,并进入指定目录
popd:回到前一个保存的目录

示例:

@echo off
c: & cd\ & md mp3 #切换到c盘并在 C:\ 建立 mp3 文件夹
md d:\mp4 #在 D:\ 建立 mp4 文件夹
cd /d d:\mp4 #更改当前目录为 d:\mp4
pushd c:\mp3 #保存当前目录,并切换当前目录为 c:\mp3
popd #恢复当前目录为刚才保存的 d:\mp4

3. 界面相关

3.1 title修改命令行窗口标题

格式:title 文本。

示例:

:: 命令行标题将显示为“自定义标题”
title 自定义标题

3.2 color修改命令行背景色、前景色

格式:color af。第一个数字表示背景色,第二个数字表示前景色。

示例:

:: 蓝底白字
color 9f
数字 颜色
0 黑色
1 蓝色
2 绿色
3 湖蓝色
4 红色
5 紫色
6 黄色
7 白色
8 灰色
9 淡蓝色
A 淡绿色
B 淡浅绿色
C 淡红色
D 淡紫色
E 淡黄色
F 亮白色

3.3 修改命令行宽高

3.4 设计一个用户菜单界面

@echo off
cls
title 终极多功能修复
:menu
cls
color 0A
echo.
echo ==============================
echo 请选择要进行的操作,然后按回车
echo ==============================
echo.
echo 1.网络修复及上网相关设置,修复IE,自定义屏蔽网站
echo.
echo 2.病毒专杀工具,端口关闭工具,关闭自动播放
echo.
echo 3.清除所有多余的自启动项目,修复系统错误
echo.
echo 4.清理系统垃圾,提高启动速度
echo.
echo Q.退出
echo.
echo.
:cho
set choice=
set /p choice= 请选择:
IF NOT "%choice%"=="" SET choice=%choice:~0,1%
if /i "%choice%"=="1" goto show
if /i "%choice%"=="2" goto show
if /i "%choice%"=="3" goto show
if /i "%choice%"=="4" goto show
if /i "%choice%"=="Q" goto endd
echo 选择无效,请重新输入
echo.
goto cho

:show
echo u choose %choice%
goto cho
:endd

3.5 实现进度条

@echo off
mode con cols=113 lines=15 &color 9f
cls
echo.
echo 程序正在初始化. . . 
echo.
echo ┌──────────────────────────────────────┐
set/p= ■<nul
for /L %%i in (1 1 38) do set /p a=■<nul&ping /n 1 127.0.0.1>nul
echo 100%%
echo └──────────────────────────────────────┘
pause

4. 变量

4.1 系统变量

这些变量系统已经给他们定义了值(包括环境变量),不需要我们来给他赋值,我们只需要调用而以。

  • %ALLUSERSPROFILE% 本地 返回“所有用户”配置文件的位置。
  • %APPDATA% 本地 返回默认情况下应用程序存储数据的位置。
  • %CD% 本地 返回当前目录字符串。
  • %CMDCMDLINE% 本地 返回用来启动当前的 的准确命令行。
  • %CMDEXTVERSION% 系统 返回当前的“命令处理程序扩展”的版本号。
  • %COMPUTERNAME% 系统 返回计算机的名称。
  • %COMSPEC% 系统 返回命令行解释器可执行程序的准确路径。
  • %DATE% 系统 返回当前日期。使用与 date /t 命令相同的格式。由 生成。有关date 命令的详细信息,请参阅 Date。
  • %ERRORLEVEL% 系统 返回上一条命令的错误代码。通常用非零值表示错误。
  • %HOMEDRIVE% 系统 返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。
  • %HOMEPATH% 系统 返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。
  • %HOMESHARE% 系统 返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。
  • %LOGONSERVER% 本地 返回验证当前登录会话的域控制器的名称。
  • %NUMBER_OF_PROCESSORS% 系统 指定安装在计算机上的处理器的数目。
  • %OS% 系统 返回操作系统名称。Windows 2000 显示其操作系统为 Windows_NT。
  • %PATH% 系统 指定可执行文件的搜索路径。
  • %PATHEXT% 系统 返回操作系统认为可执行的文件扩展名的列表。
  • %PROCESSOR_ARCHITECTURE% 系统 返回处理器的芯片体系结构。值:x86 或 IA64 基于Itanium
  • %PROCESSOR_IDENTFIER% 系统 返回处理器说明。
  • %PROCESSOR_LEVEL% 系统 返回计算机上安装的处理器的型号。
  • %PROCESSOR_REVISION% 系统 返回处理器的版本号。
  • %PROMPT% 本地 返回当前解释程序的命令提示符设置。由 生成。
  • %RANDOM% 系统 返回 0 到 32767 之间的任意十进制数字。由 生成。
  • %SYSTEMDRIVE% 系统 返回包含 Windows server operating system 根目录(即系统根目录)的驱动器。
  • %SYSTEMROOT% 系统 返回 Windows server operating system 根目录的位置。
  • %TEMP% 和 %TMP% 系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其他应用程序则需要 TMP。
  • %TIME% 系统 返回当前时间。使用与 time /t 命令相同的格式。由 生成。有关time 命令的详细信息,请参阅 Time。
  • %USERDOMAIN% 本地 返回包含用户帐户的域的名称。
  • %USERNAME% 本地 返回当前登录的用户的名称。
  • %USERPROFILE% 本地 返回当前用户的配置文件的位置。
  • %WINDIR% 系统 返回操作系统目录的位置。

示例:复制文件到当前帐号的启动目录

# 注意有空格的目录要用引号引起来
copy d:\ "%USERPROFILE%\「开始」菜单\程序\启动\"

示例:检查是否配置了ANDROID_HOME环境变量
方式一:判断对应值是否为空字符串

@echo off
if "%ADNROID_HOM%"=="" echo android home not exist
pause

方式二:直接使用define指令

@echo off
if defined ANDROID_HOME echo android home has defined
pause

示例:获取当前目录路径

echo %cd%

4.2 环境变量

  1. 查看所有环境变量
:: 命令行中打印所有环境变量
set
:: 输出环境变量到文件
set > 
  1. 查看某个环境变量
:: 查看JAVA_HOME变量值
set JAVA_HOME
  1. 设置环境变量
:: 设置一个名为NEW_VAR的环境变量
set NEW_VAR=G:\TEMP
  1. 清除某个环境变量
:: 清除NEW_VAR这个变量
set NEW_VAR=

4.3 批处理入参变量

  • %0 批处理文件本身,包括完整的路径和扩展名,可以调用批处理自身,以达到批处理本身循环的目的,也可以复制文件自身等等
  • %1 第一个参数
  • %9 第九个参数
  • %* 从第一个参数开始的所有参数

这些%1和%9可以让批处理也能带参数运行,大大提高批处理功能!

# 再命令行依次输入下述命令
echo ^@echo off>
echo echo var1 = %1 var2 = %2 var3 = %3>>
 我是a 我是b 我是c
del 

4.4 自定义变量

不需要预定义,直接set创建变量并赋值

基本格式:
set var=string 定义一个字符串变量,string内容可以不输入
set /a var=number calculation 执行数学计算
set /p var=hint: 提示用户输入,var也是一个字符串

注意:在使用set为变量赋值时,=的左右不要有空格
示例:最简单的使用方式

@echo off
set var=我是值
echo %var%
pause

示例:数值由用户键盘输入

@echo off
# var=,=号前后不要有空格
set /p var=please input any thing and end with enter:
echo your input is %var%
pause

4.5 设置网络代理

设置后只对当前 cmd 窗口上下文有效。

# 代理无用户名密码
set http_proxy=http://127.0.0.1:1080
set https_proxy=http://127.0.0.1:1080

# 具有用户名密码
set HTTP_PROXY=:port
set HTTP_PROXY_USER=username
set HTTP_PROXY_PASS=password

set HTTPS_PROXY=:port
set HTTPS_PROXY_USER=username
set HTTPS_PROXY_PASS=password

# 取消网络代理
netsh winhttp reset proxy

此处参考:windows终端命令行下使用网络代理

5. 调用三方应用程序

5.1 调用ftp

ftp是常用的下载工具,ftp界面中有40多个常用命令,自己学习了,不介绍了。这里介绍如何用dos命令行调用ftp命令,实现ftp自动登录,并上传下载,并自动退出ftp程序。可以将ftp命令组合保存为一个文本文件,然后用以下命令调用即可。

ftp -n -s:[[drive:]path]filename,filename为ftp命令文件

命令脚本文件示例:登录IP地址,用户名、密码、操作命令

open 90.52.8.3 #打开ip
user iware #用户为iware
password8848 #密码
bin #二进制传输模式
prompt
cd tmp1 #切换至iware用户下的tmp1目录
pwd
lcd d:\download #本地目录
mget * #下载tmp1目录下的所有文件
bye #退出ftp

5.2 调用7-zip

语法格式:7z [ …] <base_archive_name> […]

详细情况见7-zip帮助文件

5.3 调用VBScript程序

使用 Windows 脚本宿主,可以在命令提示符下运行脚本。 提供了用于设置脚本属性的命令行开关。

使用格式:CScript 脚本名称 [脚本选项…] [脚本参数…]

  • 脚本名称:
    带有扩展名和必需的路径信息的脚本文件名称,如d:/admin/vbscripts/。
  • 脚本选项:
    • //B 批模式:不显示脚本错误及提示信息
    • //D 启用 Active Debugging
    • //E:engine 使用执行脚本的引擎
    • //H:CScript 将默认的脚本宿主改为
    • //H:WScript 将默认的脚本宿主改为 (默认)
    • //I 交互模式(默认,与 B 相对)
    • //Job:xxxx 执行一个 WSF 工作
    • //Logo 显示徽标(默认)
    • //Nologo 不显示徽标:执行时不显示标志
    • //S 为该用户保存当前命令行选项
    • //T:nn 超时设定秒:允许脚本运行的最长时间
    • //X 在调试器中执行脚本
    • //U 用 Unicode 表示来自控制台的重定向 I/O

5.4 调用jar包

命令格式:java -jar [command]

5.5 调用exe程序

命令格式: [command]

6. 转换为可执行文件

由于批处理文件是一种文本文件,任何人都可以对其进行随便编辑,不小心就会把里面的命令破坏掉,所以如果将其转换成可执行文件,不仅执行效率会大大提高,而且不会破坏原来的功能,更能将优先级提到最高。
在DOS环境下,可执行文件的优先级由高到低依次为.com>.exe>.bat>.cmd,即如果在同一目录下存在文件名相同 的这四类文件,当只键入文件名时,DOS执行的是,如果需要执行其他三个文件,则必须指定文件的全名,如。

6.1 转换成.com文件

工具推荐:Bat2Com

6.2 转换成.exe文件

工具推荐:Bat To Exe Converter、bat2exe等

7. 参考资料

  • BAT 批处理脚本教程(详细篇我补充)_DOS/BAT_我
  • BAT脚本编写教程(比较易懂和全面)_DOS/BAT_我