只有脚踩上去才知其远近和曲折

Bat脚本基础入门

相关命令

Dos 命令

命令 解释
ver 在DOS窗口下显示版本信息
winver 弹出一个窗口显示版本信息(内存大小、系统版本、补丁版本、计算机名)
format 盘符 /FS:类型 格式化磁盘,类型:FAT、FAT32、NTFS ,例:Format D: /FS:NTFS
md 目录名 创建目录
replace 源文件 要替换文件的目录 替换文件
ren 原文件名 新文件名 重命名文件名
tree 以树形结构显示出目录,用参数-f 将列出第个文件夹中文件名称
type 文件名 显示文本文件的内容
more 文件名 逐屏显示输出文件
taskmgr 调出任务管理器
chkdsk /F D: 检查磁盘D并显示状态报告;加参数/f并修复磁盘上的错误
path 路径\可执行文件的文件名 为可执行文件设置一个路径。
exit 退出cmd.exe程序或目前,用参数/B则是退出当前批处理脚本而不是cmd.exe
regedit /s 注册表文件名 导入注册表;参数/S指安静模式导入,无任何提示;
regedit /e 注册表文件名 导出注册表
cacls 文件名 查看文件的访问用户权限列表
cacls 文件名 参数 显示或修改文件访问控制列表(ACL)——针对NTFS格式时。参数:/D 用户名:设定拒绝某用户访问;/P 用户名:perm 替换指定用户的访问权限;/G 用户名:perm 赋予指定用户访问权限;Perm 可以是: N 无,R 读取, W 写入, C 更改(写入),F 完全控制;例:cacls D:\test.txt /D pub 设定d:\test.txt拒绝pub用户访问。
netsh 查看或更改本地网络配置情况
find 参数 “字符串” 文本 在文件中搜索字符串。参数:/V ,显示所有未包含指定字符串的行。/C ,仅显示包含字符串的行数。/N ,显示行号。 /I ,搜索字符串时忽略大小写。
call 路径\批处理文件名 从批处理程序中调用另一个批处理程序 (更多说明见call /?)
color 颜色值 设置cmd控制台前景和背景颜色;0=黑、1=蓝、2=绿、3=浅绿、4=红、5=紫、6=黄、7=白、8=灰、9=淡蓝、A=淡绿、B=淡浅绿、C=淡红、D=淡紫、E=淡黄、F=亮白
title 标题名字 更改CMD窗口标题名字
prompt 名称 更改cmd.exe的显示的命令提示符(把C:\、D:\统一改为:EntSky\ )
set 指定环境变量名称=要指派给变量的字符 设置环境变量
set 显示当前所有的环境变量
set p(或其它字符) 显示出当前以字符p(或其它字符)开头的所有环境变量
pause 暂停批处理程序,并显示出:请按任意键继续….
attrib 文件名(目录名) 查看某文件(目录)的属性
attrib 文件名 -A -R -S -H 或 +A +R +S +H 去掉(添加)某文件的 存档,只读,系统,隐藏 属性;用+则是添加为某属性
dir 查看文件,参数:/Q显示文件及目录属系统哪个用户,/T:C显示文件创建时间,/T:A显示文件上次被访问时间,/T:W上次被修改时间 (类似于ls)
date /t 、 time /t 使用此参数即”DATE/T”、”TIME/T”将只显示当前日期和时间,而不必输入新日期和时间
start 程序名或命令 /max 或/min 新开一个新窗口并最大化(最小化)运行某程序或命令
del /S /Q 目录 或用:rmdir /s /Q 目录 /S删除目录及目录下的所有子目录和文件。同时使用参数/Q 可取消删除操作时的系统确认就直接删除。(二个命令作用相同)
move 盘符\路径\要移动的文件名 存放移动文件的路径\移动后文件名 移动文件,用参数/y将取消确认移动目录存在相同文件的提示就直接覆盖
fc one.txt two.txt > 3st.txt 对比二个文件并把不同之处输出到3st.txt文件中,”> “和”> >” 是重定向命令
at 查看所有的计划任务
at id号 开启已注册的某个计划任务
at /delete 停止所有计划任务,用参数/yes则不需要确认就直接停止
at id号 /delete 停止某个已注册的计划任务
at \ip time 程序名(或一个命令) /r 在某时间运行对方某程序并重新启动计算机
telnet ip 端口 远程登陆服务器,默认端口为23
open ip 连接到IP(属telnet登陆后的命令)
telnet 在本机上直接键入telnet 将进入本机的telnet
finger username @host 查看最近有哪些用户登陆
copy 路径\文件名1 路径\文件名2 /y 复制文件1到指定的目录为文件2,用参数/y就同时取消确认你要改写一份现存目录文件
copy c:\srv.exe \ip\admin$ 复制本地c:\srv.exe到对方的admin下
cppy 1st.jpg/b+2st.txt/a 3st.jpg 将2st.txt的内容藏身到1st.jpg中生成3st.jpg新的文件,注:2st.txt文件头要空三排,参数:/b指二进制文件,/a指ASCLL格式文件
copy\\ip\admin\svv.exe c:\ 或:copy\\ip\admin\*.* 复制对方admini$共享下的srv.exe文件(所有文件)至本地C:
xcopy 要复制的文件或目录树 目标地址\目录名 复制文件和目录树,用参数/Y将不提示覆盖相同文件
route print 显示出IP路由,将主要显示网络地址Network addres,子网掩码Netmask,网关地址Gateway addres,接口地址Interface
echo on或off 打开或关闭echo,仅用echo不加参数则显示当前echo设置
echo 信息 在屏幕上显示出信息
echo 信息 >> pass.txt 将”信息”保存到pass.txt文件中
命令 解释
msg /server:对方电脑IP * 对方电脑屏幕要弹出的文本” 向对方电脑发送一条文本提示,回车后对方屏幕即可弹出消息。msg是一款局域网命令,无法在广域网上使用。需要添加windows凭据。
net start 查看开启了哪些服务
net start 服务名 开启服务;(如:net start telnet, net start schedule)
net stop 服务名 停止某服务
net user 查看有哪些用户
net user 帐户名 查看帐户的属性
net user 用户名 密码 /add 建立用户
net user guest /active:yes 激活guest用户
net use \ip\ipc$ ” ” /user:” “ 建立IPC空链接
net use \ip\ipc$ “密码” /user:”用户名” 建立IPC非空链接
net use h: \ip\c$ “密码” /user:”用户名” 直接登陆后映射对方C:到本地为H:
net use h: \ip\c$ 登陆后映射对方C:到本地为H:
net use \ip\ipc$ /del 删除IPC链接
net use h: /del 删除映射对方到本地的为H:的映射
net localgroup administrators 用户名 /add 把”用户”添加到管理员中使其具有管理员权限,注意:administrator后加s用复数
net time \目标ip 查看对方时间
net time \目标ip /set 设置本地计算机时间与”目标IP”主机的时间同步,加上参数/yes可取消确认信息
net view 查看本地局域网内开启了哪些共享
net view \ip 查看对方局域网内开启了哪些共享
net config 显示系统网络设置
net logoff 断开连接的共享
net pause 服务名 暂停某服务
net share 查看本地开启的共享
net share ipc$ 开启ipc$共享
net share ipc$ /del 删除ipc$共享
net share c$ /del 删除C:共享
net user guest 12345 用guest用户登陆后用将密码改为12345
net password 密码 更改系统登陆密码
netstat -a 查看开启了哪些端口,常用netstat -an
netstat -n 查看端口的网络连接情况,常用netstat -an
netstat -v 查看正在进行的工作
netstat -p 协议名 例:netstat -p tcq/ip 查看某协议使用情况(查看tcp/ip协议使用情况)
netstat -s 查看正在使用的所有协议使用情况
nbtstat -A ip 对方136到139其中一个端口开了的话,就可查看对方最近登陆的用户名(03前的为用户名)-注意:参数-A要大写
ping ip(或域名) 向对方主机发送默认大小为32字节的数据,参数:”-l[空格]数据包大小”;”-n发送数据次数”;”-t”指一直ping。
ping -t -l 65500 ip 死亡之ping(发送大于64K的文件并一直ping就成了死亡之ping)
ipconfig (winipcfg) 用于windows NT及XP(windows 95 98)查看本地ip地址,ipconfig可用参数”/all”显示全部配置信息
tlist -t 以树行列表显示进程(为系统的附加工具,默认是没有安装的,在安装目录的Support/tools文件夹内)
kill -F 进程名 加-F参数后强制结束某进程(为系统的附加工具,默认是没有安装的,在安装目录的Support/tools文件夹内)
del -F 文件名 加-F参数后就可删除只读文件,/AR、/AH、/AS、/AA分别表示删除只读、隐藏、系统、存档文件,/A-R、/A-H、/A-S、/A-A表示删除除只读、隐藏、系统、存档以外的文件。例如”DEL/AR .“表示删除当前目录下所有只读文件,”DEL/A-S .“表示删除当前目录下除系统文件以外的所有文件
shutdown /参数 关闭或重启本地或远程主机。 参数说明:/S 关闭主机,/R 重启主机, /T 数字 设定延时的时间,范围0~180秒之间, /A取消开机,/M //IP 指定的远程主机。 例:shutdown /r /t 0 立即重启本地主机(无延时)
taskill /参数 进程名或进程的pid 终止一个或多个任务和进程。 参数说明:/PID 要终止进程的pid,可用tasklist命令获得各进程的pid,/IM 要终止的进程的进程名,/F 强制终止进程,/T 终止指定的进程及他所启动的子进程。
tasklist 显示当前运行在本地和远程主机上的进程、服务、服务各进程的进程标识符(PID)。 参数说明:/M 列出当前进程加载的dll文件,/SVC 显示出每个进程对应的服务,无参数时就只列出当前的进程。
tracert -参数 ip(或计算机名) 跟踪路由(数据包),参数:”-w数字”用于设置超时间隔。
Netsh wlan show 列出Wi-Fi配置文件,如:netsh wlan show profile 可得到列出WiFi名称和密码,前提是已经连接到该WiFi

计算机运行命令全集

命令 解释
winver 检查Windows版本
wmimgmt.msc 打开windows管理体系结构
wupdmgr windows更新程序
winver 检查Windows版本
wmimgmt.msc 打开windows管理体系结构
wupdmgr windows更新程序
wscript windows脚本宿主设置
write 写字板winmsd系统信息
wiaacmgr 扫描仪和照相机向导
winchat XP自带局域网聊天
mem.exe 显示内存使用情况
Msconfig.exe 系统配置实用程序
mplayer2 简易widnows media player
mspaint 画图板
mstsc 远程桌面连接
mplayer2 媒体播放机
magnify 放大镜实用程序
mmc 打开控制台
mobsync 同步命令
dxdiag 检查DirectX信息
drwtsn32 系统医生
devmgmt.msc 设备管理器
dfrg.msc 磁盘碎片整理程序
diskmgmt.msc 磁盘管理实用程序
dcomcnfg 打开系统组件服务
ddeshare 打开DDE共享设置
dvdplay DVD播放器
net stop messenger 停止信使服务
net start messenger 开始信使服务
notepad 打开记事本
nslookup 网络管理的工具向导
ntbackup 系统备份和还原
narrator 屏幕”讲述人”
ntmsmgr.msc 移动存储管理器
ntmsoprq.msc 移动存储管理员操作请求
netstat -an (TC)命令检查接口
syncapp 创建一个公文包
sysedit 系统配置编辑器
sigverif 文件签名验证程序
sndrec32 录音机
shrpubw 创建共享文件夹
secpol.msc 本地安全策略
syskey 系统加密,一旦加密就不能解开,保护windows xp系统的双重密码
services.msc 本地服务设置
Sndvol32 音量控制程序
sfc.exe 系统文件检查器
sfc /scannow windows文件保护
tsshutdn 60秒倒计时关机命令
tourstart xp简介(安装完成后出现的漫游xp程序)
taskmgr 任务管理器
eventvwr 事件查看器
eudcedit 造字程序
explorer 打开资源管理器
packager 对象包装程序
perfmon.msc 计算机性能监测程序
progman 程序管理器
regedit.exe 注册表
rsop.msc 组策略结果集
regedt32 注册表编辑器
rononce -p 15秒关机
regsvr32 /u *.dll 停止dll文件运行
regsvr32 /u zipfldr.dll 取消ZIP支持
cmd.exe CMD命令提示符
chkdsk.exe Chkdsk磁盘检查
certmgr.msc 证书管理实用程序
calc 启动计算器
charmap 启动字符映射表
cliconfg SQL SERVER 客户端网络实用程序
Clipbrd 剪贴板查看器
conf 启动netmeeting
compmgmt.msc 计算机管理
cleanmgr **整理
ciadv.msc 索引服务程序
osk 打开屏幕键盘
odbcad32 ODBC数据源管理器
oobe/msoobe /a 检查XP是否激活
lusrmgr.msc 本机用户和组
logoff 注销命令
iexpress 木马捆绑工具,系统自带
Nslookup IP地址侦测器
fsmgmt.msc 共享文件夹管理器
utilman 辅助工具管理器
gpedit.msc 组策略
settings 打开设置

IIS服务命令

命令 解释
iisreset /reboot 重启win2k计算机(但有提示系统将重启信息出现)
iisreset /start或stop 启动(停止)所有Internet服务
iisreset /restart 停止然后重新启动所有Internet服务
iisreset /status 显示所有Internet服务状态
iisreset /enable或disable 在本地系统上启用(禁用)Internet服务的重新启动
iisreset /rebootonerror 当启动、停止或重新启动Internet服务时,若发生错误将重新开机
iisreset /noforce 若无法停止Internet服务,将不会强制终止Internet服务
iisreset /timeout Val在到达逾时间(秒)时,仍未停止Internet服务,若指定/rebootonerror参数,则电脑将会重新开机。预设值为重新启动20秒,停止60秒,重新开机0秒。
ftp -v -d -i -n -g[主机名] -v 显示远程服务器的所有响应信息。
-d 使用调试方式。
-n 限制ftp的自动登录,即不使用.netrc文件。
-g 取消全局文件名。
help [命令] 或 ?[命令] 查看命令说明
bye 或 quit 终止主机FTP进程,并退出FTP管理方式
pwd 列出当前远端主机目录
put 或 send 本地文件名 [上传到主机上的文件名] 将本地一个文件传送至远端主机中
get 或 recv [远程主机文件名] [下载到本地后的文件名] 从远端主机中传送至本地主机中
mget [remote-files] 从远端主机接收一批文件至本地主机
mput local-files 将本地主机中一批文件传送至远端主机
dir 或 ls [remote-directory] [local-file] 列出当前远端主机目录中的文件.如果有本地文件,就将结果写至本地文件
ascii 设定以ASCII方式传送文件(缺省值)
bin 或 image 设定以二进制方式传送文件
bell 每完成一次文件传送,报警提示
cdup 返回上一级目录
close 中断与远程服务器的ftp会话(与open对应)
open host[port] 建立指定ftp服务器连接,可指定连接端口
delete 删除远端主机中的文件
mdelete [remote-files] 删除一批文件
mkdir directory-name 在远端主机中建立目录
rename [from] [to] 改变远端主机中的文件名
rmdir directory-name 删除远端主机中的目录
status 显示当前FTP的状态
system 显示远端主机系统类型
user user-name [password] [account] 重新以别的用户名登录远端主机
open host [port] 重新建立一个新的连接
prompt 交互提示模式
macdef 定义宏命令
lcd 改变当前本地主机的工作目录,如果缺省,就转到当前用户的HOME目录
chmod 改变远端主机的文件权限
case 当为ON时,用MGET命令拷贝的文件名到本地机器中,全部转换为小写字母
cd remote-dir 进入远程主机目录
cdup 进入远程主机目录的父目录
! 在本地机中执行交互shell,exit回到ftp环境,如!ls*.zip

Bat语法

参考文档:

windows BAT 批处理常见命令解析

windows bat 批处理脚本编写指南

1. Hello World

1)code

@echo off
rem This is a "Hello World" program.
echo Hello World!
echo=

打开cmd命令窗口,切换到D:\cmdtest目录,运行helloworld 或 helloworld.bat

2)注意

  • @echo off,关闭之后所有命令的回显,不然bat文件中每条指令会在cmd命令窗口显示
  • rem,注释,还有::也表示注释,两者区别,大家请小度
  • echo,输出
  • echo=,输出空白行

2. 变量

1)变量声明

变量无需声明可直接引用,其值为空字符串,并且大小写不敏感。可使用defined关键字或是否为空字符串""判断变量是否为空

rem 将代码保存为bat文件执行
@echo off
rem set var2="var2"
if not defined var2 ( 
    echo var2 is not defined, the value is: %var2%
) else ( 
    echo var2 is defined, the value is: %var2%
)

if "%var2%"=="" (
    echo var2 is not defined, the value is: %var2%
) else (
    echo var2 is defined, the value is: %var2%
)
  • 第一次会输出两遍 var2 is not defined, the value is:
  • 先给变量赋值 set var2=“var2”,则会输出两遍 var2 is defined, the value is: “var2”
  • 如果变量set var2="var2"赋值过,然后将赋值set var2="var2"语句注释掉并运行,依然会输出 var2 is defined, the value is: “var2”,这是因为bat 脚本变量不特殊处理的话是全局变量,只要脚本是在同一个 cmd 命令框运行便会存在,可通过set var2=清除

2)变量赋值

@echo off
set var1=2+2
set /a var2=2+2
set /p var3=Please input a number:
set /p md5=<file_info.md5
echo var1: %var1%
echo var2: %var2%
echo var3: %var3%
echo md5: %md5%

输出结果:

D:\cmdtest>var
Please input a number:100
var1: 2+2
var2: 4
var3: 100
md5: 76adfafs76776…

  • 变量赋值时等号前后不能有空格,类似set a = 1会报错
  • /a 是表达式运算,仅适合32位整型运算,可以是负数
  • /p 是提示输入,将输入值赋值给变量
  • set /p md5=<file_info.md5, 读取 md5 文件内容并赋值给 md5 变量
  • 可通过set a=清空变量

3)变量读取

  • 可通过%var%, 读取变量值
  • set var,列出 var 开头的所有变量
  • set,列出所有变量,如系统环境变量 TEMP、PATH 等也会列举出来
  • !var!,两个感叹号,延迟读取变量值,详看 “变量延迟” 部分
  • 需要了解的一些系统内置变量
命令 解释
%date% 系统日期,类似:2020/02/29 周六
%time% 获取系统时间,类似:17:13:15.18
%cd% 获取当前目录
%RANDOM% 系统 返回 0 到 32767 之间的任意十进制数字
%NUMBER_OF_PROCESSORS% 系统 指定安装在计算机上的处理器的数目
%PROCESSOR_ARCHITECTURE% 系统 返回处理器的芯片体系结构。值:x86 或 IA64 基于Itanium
%PROCESSOR_IDENTFIER% 系统 返回处理器说明。
%PROCESSOR_LEVEL% 系统 返回计算机上安装的处理器的型号
%PROCESSOR_REVISION% 系统 返回处理器的版本号
%COMPUTERNAME% 系统 返回计算机的名称
%USERNAME% 本地 返回当前登录的用户的名称
%USERPROFILE% 本地 返回当前用户的配置文件的位置
%~dp0 bat脚本文件所在目录

4)变量作用域

默认为全局变量(Global),可使用setlocal命令将变量作用域设置为 local,直到endlocalexit命令,或 bat 文件执行结束,变量 local 作用域也结束并恢复到 global 作用域

@echo off
setlocal
set v=Local Variable
echo v=%v%

输出结果:

D:\cmdtest>set v=Global Variable
D:\cmdtest>var_scope
v=Local Variable
D:\cmdtest>echo v=%v%
v=Global Variable
D:\cmdtest>

setlocal命令注释掉,然后执行上述代码,会发现变量 v 最终输出的是 “Local Variable”,即外面设置的变量 v被 bat 文件中的变量 v 玷污了。

5)变量延迟

@echo off
set a=1
set /a a+=1 > nul & echo %a%

运行后将输出1,而不是2,原因如下:

当我们准备执行一条命令的时候,命令解释器会先将命令读取,如果命令中有环境变量,那么就会将变量的值先读取来出,然后在运行这条命令,如:echo %a%,当我们执行这条命令的时候,命令解释器会先读出%a%的值,即 1,然后执行 echo,所以输出 1。

然而,上述脚本本意是输出 a+=1 运算后的 a 值,即 2。ba t脚本提供了变量延迟,即变量在使用时再读取,上述代码修改如下:

@echo off
setlocal EnableDelayedExpansion
set a=1
set /a a+=1 > nul & echo !a!
  • setlocal EnableDelayedExpansion 开启变量延迟,无需关注变量延迟如何关闭,有时为了代码简洁也写成:@echo off & setlocal EnableDelayedExpansion
  • !a!,两个叹号,变量才会延迟读取

6)特殊变量

上文已经提及很多内置变量或命令,此处的特殊变量指命令行参数,比如运行test.bat arg1 arg2,带了 2 个参数arg1,arg2,那么如何表示脚本文件本身,参数1、参数2如何获取呢?

@echo off & setlocal
echo arg0=%0
echo arg1=%1
echo arg1 no quotes=%~1
echo batfile fullpath=%~f0
echo batfile=%~n0
echo batfolder=%~dp0

D:\cmdtest>var_arg “marcus”
arg0=var_arg
arg1=”marcus”
arg1 no quotes=marcus
batfile fullpath=D:\cmdtest\var_arg.bat
batfile=var_arg
batfolder=D:\cmdtest\

命令 解释
%* 表示参数列表,比如:var_arg.bat arg1 arg2 arg3,则 %* = arg1 arg2 arg3
%0 表示脚本文件名,调用时var_arg则%0=var_arg,若调用时var_arg.bat则%0=var_arg.bat
%1 表示第一个参数
%~1 第一个参数去引号,如:var_arg.bat “arg1”,%~1得到arg1
%~f0 脚本文件完整路径名
%~dp0 脚本文件所在目录

3. 返回码和errorlevel

1)返回码

通常来说一条命令的执行结果返回的值只有两个,0 表示”成功”,1 表示”失败”,实际上,errorlevel 返回值可以是一个任何整型值,一般只定义在0~255之间。

@echo off
rem return code demo
exit /b %1

D:\cmdtest>returncode 0
D:\cmdtest>echo %errorlevel%
0
D:\cmdtest>returncode 1
D:\cmdtest>echo %errorlevel%
1
D:\cmdtest>returncode -1
D:\cmdtest>echo %errorlevel%
-1

bat 脚本文件中exit指定的 code 即返回码,就是下一行获取到的 errorlevel 值,从 demo 可以看出 errorlevel 甚至可以是负值。
如果 bat 脚本文件中没有`exit code 命令,bat 文件执行结束后,会不会有返回码?没有,有点类似 void 函数,因此 errorlevel 仍然是上次的 -1。

2)errorlevel如何使用

通常来说,可以根据errorlevel是否等于0来判断脚本是否成功执行(0表示成功,>0值表示失败),若明确脚本返回码的情况下,也可以根据具体返回码值做具体处理,DEMO如下:假设执行脚本后,errorlevel=0,则

D:\cmdtest>if errorlevel 1 (echo fail) else (echo success)
success
D:\cmdtest>if %errorlevel% EQU 0 (echo success) else (echo fail)
success

  • errorlevel 1errorlevel >= 1
  • %errorlevel% EQU 0errorlevel == 0
  • EQU 数字比较关系详看 “if判断” 部分

4. stdin, stdout, stderr

变量 解释
stdin 标准输入,重定向时也用数字0表示
stdout 标准输出,重定向时也用数字1表示
stderr 错误输出,重定向时也用数字2表示

1)重定向

标准输出重定向

dir > dir.txt   
:: dir文件、目录列表输出到dir.txt, dir.txt文件重新生成
dir >> dir.txt
:: dir文件、目录列表添加到dir.txt, dir.txt存在则添加,否则新建
echo line1 > line.txt
:: 覆盖line.txt,内容为line1
type con > line.txt
:: 响应键盘输入,直到按ctrl+z结束,输出到line.txt文件

错误输出重定向

d:\cmdtest\stdout>dir aaa 2>error.txt
d:\cmdtest\stdout>type error.txt
找不到文件

标准、错误输出合并
通常我们会将标准输出和错误输出合并到一个文件,如下所示:

d:\cmdtest\stdout>DIR SomeFile.txt > output.txt 2>&1
d:\cmdtest\stdout>type output.txt
驱动器 D 中的卷是 软件
卷的序列号是 65F3-3762

d:\cmdtest\stdout 的目录

找不到文件

遍历SomeFile.txt,先将遍历结果输出到output.txt,如果出错则将错误信息添加到
output.txt(此处的“找不到文件”)。

标准输入
将某个文件作为内容输入,用 < 表示,如下所示:

D:\cmdtest\stdout>sort < countries.txt
America
Australia
China
England

D:\cmdtest\stdout>type countries.txt
China
America
England
Australia
D:\cmdtest\stdout>

将countries.txt文件中的内容进行排序显示。

2)输出挂起、丢弃

用NUL表示丢弃任何程序输出,2个经典应用:

  • 字符串查找,findstrex.bat
@echo off & setlocal
set str1=The most severe place of New SARS is Wuhan.
set str2=%~1
echo %str1% | findstr /i "%str2%" > nul && (echo "found") || (echo "not found")

D:\cmdtest>findstrex.bat wuhan
“found”

  • 程序暂停若干秒
@echo off
echo "program sleep 5 seconds, start..."
ping /n 5 127.1>nul
echo "program sleep 5 seconds, end..."
exit /b 0

先输出 “program sleep 5 seconds, start…”,5秒后再输出 “program sleep 5 seconds, end…”

3)管道符 | 使用

管道符 | 通常用于一个命令的输出作为另一个命令的输入,如:

DIR /B | SORT

DIR /B,/B 使用空格式(没有标题信息或摘要)。
DIR /B | SORT,将dir /b结果进行字符串排序

5. if 判断与&、&&、||

顺序、选择和循环是编程语言的常见3种语句,bat 脚本也是如此,bat 脚本if选择语句语法如下:

if 条件 (do...)
if 条件 (do...) else (do ...)

注意:

  • 条件只能是单个条件,不能用andor进行条件与或运算,但是可以使用not进行条件非运算
  • 没有 elseif

1)文件是否存在,isexist.bat

@echo off
IF EXIST "temp.txt" (
    ECHO found
) ELSE (
    ECHO not found
)

2)变量是否定义

IF "%var%"=="" (TODO)
IF NOT DEFINED var (TODO)

3)比较字符串是否相等

@echo off & setlocal
set /p arg1="please input a string:"
set /p arg2="please input another string:"
if %arg1%==%arg2% (echo %arg1% equals %arg2%) else (echo %arg1% not equals %arg2%)
if not %arg1%==%arg2% (echo %arg1% not equals %arg2%) else (echo %arg1% equals %arg2%)
if %arg1% equ %arg2% (echo %arg1% equals %arg2%) else (echo %arg1% not equals %arg2%)
if %arg1% neq %arg2% (echo %arg1% not equals %arg2%) else (echo %arg1% equals %arg2%)

set /p name="please input your name: "
if /i "%name%"=="marcus" ( echo You are Marcus! ) else ( echo You are not Marcus! )

D:\cmdtest\lianxi>str
please input a string:aa
please input another string:aa
aa equals aa
aa equals aa
aa equals aa
aa equals aa
please input your name: aaa
You are not Marcus!

  • 两个字符串变量是否相等,可以使用==equ;不等则可以使用 not ==neq
  • 字符串变量与常量比较,请带双引号,如:”%name%”==“marcus”
  • /i,表示忽略大小写,类似 java 的 equalsIgnoreCase

4)数字比较

@echo off & setlocal
set num1=1
set num2=2
if %num1% EQU %num2% (echo %num1% == %num2%) else (echo echo %num1% != %num2%)
命令 解释
EQU 等于
NEQ 不等于
LSS 小于
LEQ 小于等于
GTR 大于
GEQ 大于或等于

5)程序返回码处理

if errorlevel 1 (TODO)
if %errorlevel% equ 0 (TODO)

6)&、&&、||

命令 解释
& 顺序执行多条命令,而不管命令是否执行成功。如: @echo off & setlocal
&& 顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令
|| 顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令(即:只有前面命令执行错误时才执行后面命令),findstr 命令时经常会使用 && 和 || 符号,分别表示:找到执行…,没找到执行…
set str="Apple,Huawei,Xiaomi,Oppo,Vivo"
echo  %str% | findstr /i "asus" > nul && (FOUND,TOTO) || (NOTFOUND, TODO)

6. 循环

bat 脚本实现循环有 2 种方式:使用gotofor循环,简单 demo 如下:

goto实现方式,1-10的循环:

@echo off
set var=0
rem ************loop start.
:continue
set /a var+=1
echo loop time: %var%
if %var% lss 10 goto continue
rem ************loop end.
echo loop execution finished.

for /L in (start, step, end) do ():

@echo off
set var=0
rem ************loop start.
for /L %%i in (1,1,10) do (echo loop time: %%i)
rem ************loop end.
echo loop execution finished.
  • bat 脚本,循环中并没有continuebreak等中断,只能通过goto跳转跳出循环
  • 推荐使用 for循环实现
  • for循环,bat 文件中变量使用%%i,在 cmd 命令框则使用%i
  • 可以在 cmd 命令框中使用 for /? 查看for命令使用说明。

1)for 基础概念

对一组文件中的每一个文件执行某个特定命令。

FOR %variable IN (set) DO command [command-parameters]
  • %variable 指定一个单一字母可替换的参数。

  • (set) 指定一个或一组文件。可以使用通配符。

  • command 指定对每个文件执行的命令。

  • command-parameters 为特定命令指定参数或命令行开关。

在批处理程序中使用FOR命令时,指定变量请使用%%variable 而不要用%variable。变量名称是区分大小写的,所以%i不同于%I

如果启用命令扩展,则会支持下列 FOR 命令的其他格式:

FOR /D %variable IN (set) DO command [command-parameters]

如果集中包含通配符,则指定与目录名匹配,而不与文件名匹配。

FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

检查以[drive:]path为根的目录树,指向每个目录中的 FOR 语句。

如果在 /R 后没有指定目录规范,则使用当前目录。如果集仅为一个单点(.)字符,则枚举该目录树。

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)

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]

或者,如果有 usebackq 选项:

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]
:: …

另外,FOR变量参照的替换已被增强。您现在可以使用下列

语法 解释
%~I 删除任何引号(“),扩展 %I
%~fI 将 %I 扩展到一个完全合格的路径名
%~dI 仅将 %I 扩展到一个驱动器号
%~pI 仅将 %I 扩展到一个路径
%~nI 仅将 %I 扩展到一个文件名
%~xI 仅将 %I 扩展到一个文件扩展名
%~sI 扩展的路径只含有短名
%~aI 将 %I 扩展到文件的文件属性
%~tI 将 %I 扩展到文件的日期/时间
%~zI 将 %I 扩展到文件的大小
%~dpI 仅将 %I 扩展到一个驱动器号和路径
%~nxI 仅将 %I 扩展到一个文件名和扩展名
%~fsI 仅将 %I 扩展到一个带有短名的完整路径名
%~PATH:I 查找列在路径环境变量的目录,并将到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串可以组合修饰符来得到多重结果:PATH:I 搜索列在路径环境变量的目录,并将 %I 扩展到找到的第一个驱动器号和路径。
%~ftzaI 将 %I 扩展到类似输出线路的 DIR

在以上例子中,%IPATH可用其他有效数值代替。%~语法用一个有效的FOR变量名终止。选取类似%I的大写变量名比较易读,而且避免与不分大小写的组合键混淆。

1)FOR %variable IN (set) DO command [command-parameters]

下述代码请复制到bat文件执行

@echo off
rem 遍历字符串
for %%i in (Hangzhou Ningbo Wenzhou Shaoxin) do echo %%i

rem 遍历USERPROFILE下的文件
FOR %%i IN (%USERPROFILE%\*) DO ECHO %%i

2)/D /R参数

代码请在 cmd 命令框中运行

:: 遍历目录
:: 语法:FOR /D %variable IN (set) DO command [command-parameters]
rem 遍历文件目录
FOR /D %I IN (%USERPROFILE%\*) DO @ECHO %I

:: 递归遍历
:: 语法:FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
rem 递归遍历文件
FOR /R "%TEMP%" %I IN (*) DO @ECHO %I
rem 递归遍历文件目录
FOR /R "%TEMP%" /D %I IN (*) DO @ECHO %I

3)/L 参数

下述代码请在 cmd 命令框中运行,@echo 表示关闭echo回显

FOR /L %variable IN (start,step,end) DO command [command-parameters]
该集表示以增量形式从开始到结束的一个数字序列。
rem (1,1,5)将产生序列 1 2 3 4 5
FOR /L %i in (1,1,5) do @echo %i

rem (5,-1,1)将产生序列(5 4 3 2 1)
FOR /L %i in (5,-1,1) do @echo %i

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]
  • fileset 为一个或多个文件名。继续到 fileset 中的下一个文件之前,每份文件都被打开、读取并经过处理。处理包括读取文件,将其分成一行行的文字,然后将每行解析成零或更多的符号。然后用已找到的符号字符串变量值调用 For 循环。

  • 以默认方式,/F 通过每个文件的每一行中分开的第一个空白符号。跳过空白行。

  • 您可通过指定可选 “options” 参数替代默认解析操作。这个带引号的字符串包括一个或多个指定不同解析选项的关键字。这些关键字为
    • eol=c,指一个行注释字符的结尾(就一个)。
    • skip=n,指在文件开始时忽略的行数。
    • delims=xxx,指分隔符集。这个替换了空格和跳格键的默认分隔符集。
    • tokens=x,y,m-n,指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n 格式为一个范围。通过 nth 符号指定 mth。如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。

下述代码请保存为 bat 文件执行

@echo off
rem 分割字符串
for /f "delims=, tokens=1,2,*" %%j in ("Hangzhou,Ningbo,Wenzhou") do echo %%j,%%k,%%l

rem 逐行读取文件
for /f %%j in (d:\cmdtest\stdout\line.txt) do echo %%j

rem 执行命令,并将执行结果逐行读取
for /f %%j in ('wmic process get caption') do echo %%j
123456789

delims,tokens,skip 选项说明

  • delims,分隔符,默认是空格,逐行读取文件时;若行内容中有空格,请指定delims,否则只读取空格前的单词
  • tokens,从第几列开始读取;tokens=2,* 表示第二列开始读取%%i,第三列开始赋值给%%jtokens=2,3,*表示第二列开始读取%%i,第三列赋值给%%j,第四列开始赋值给%%k
  • skip,跳过前几行

7. 函数或子程序实现

bat 脚本没有显性的 function、sub 等关键字,我们可以通过goto变相实现函数,局部代码重用。

@echo off & setlocal
rem This is a simple calculator.
rem usage: calc + 3 5, result is 3+5=8.

set m=%~1
set a=%~2
set b=%~3
set result=0
if "%m%"=="+" goto add
if "%m%"=="-" goto sub
if "%m%"=="*" goto mul
if "%m%"=="/" goto div
echo "invalid arguments, usage: calc + 3 5, result is 3+5=8."
goto :eof

:add
set /a result=a+b
goto result

:sub
set /a result=a-b
goto result

:mul
set /a result=a*b
goto result

:div
set /a result=a/b
goto result

:result
echo %a% %m% %b% = %result%

D:\cmdtest\lianxi>calc s 1 2
“invalid arguments, usage: calc + 3 5, result is 3+5=8.”
D:\cmdtest\lianxi>calc + 1 2
1 + 2 = 3
D:\cmdtest\lianxi>calc – 1 2
1 – 2 = -1

  • eof, 此处直接退出批处理,等同于exit
  • 在函数序执行时,执行完别忘记跳转到类似:eof程序结束处以免干扰其它函数执行,如 demo 中的 add 执行完后若没有goto result,将继续执行 sub 函数。
  • 函数定义、返回值如何处理等可以参考 “bat批处理脚本 函数使用说明 函数调用结果如何返回”

8.补充

@echo off 和 echo off

  • @echo off表示执行了这条命令后关闭所有命令(包括本身这条命令)的回显。@的作用就是关闭紧跟其后的一条命令的回显。
  • echo off命令则表示关闭其他所有命令(不包括本身这条命令)的回显。

pause

pause也是一条命令,作用就是使程序暂停,也就是输出“请按任意键继续…”的原因。

:: 和 rem

rem::都起到注释的作用,然而又有些不同。

  • rem是一条命令,在运行的时候相当于把rem本身及其后面的内容置空。既然它是一条命令,就必须处于单独的一行或者有类似“&”的连接符号连接。

  • 批处理遇到以冒号 “:” 开头的行时(忽略冒号前的空格),会将其后的语句识别为 “标记” 而不是命令语句,因此类似 “:label” 这样的东东在批处理中仅仅是一个标记。

  • 对于 “::” 而言,之所以可以达到注释的效果,是因为第二个 “:” 不是标签的合法字符(把它换成 \ ; . 等等都行),它不被当作一个合法的标签。这一点很好理解,如果在你的批处理中有一个永远用不到的标签hero,那么你就可以用 “:hero” 打头来作为注释。只不过冒号有其先天的优越性–语法上的问题。

“:hero”可能出现的语法问题

我们现在回过头来看看call。比如 “call:hero”,为什么要有冒号?这是为了与文件hero区分。在复合语句中使用 “:” 经常会出问题。那么究竟什么时候会出现问题?

例1:

@echo off
@ %%i
for %%i in (a b c) do (
    :来瓶啤酒
    echo hero!
    echo %%i
)

pause

这个运行没问题。

注:%%i 是 for 命令中独有的变量参数,由 for 命令进行解释,而且仅在 for 循环中有效。

例2:

@echo off
for %%i in (a b c) do (
    echo hero!
    :来瓶啤酒
    echo %%i
)

pause

这个运行也没问题。

例3:

@echo off
for %%i in (a b c) do (
    echo hero!
    echo %%i
    :来瓶啤酒
)

pause

这个就有问题了。

例4:

@echo off
if a==a (
    echo super!
    echo hero!
    :来瓶啤酒
)

pause

这个也有问题。

例3 和 例4 都提示 “此时不应该有)” 。可得到一个猜想——标签所在行的下一行不能是后括号“)”。不过很遗憾,看例5

例5:

@echo off
echo super!
echo hero!
:来瓶啤酒
)

pause

运行没问题,看来问题还出在复合语句上而不仅仅是后括号 “)” 上。

结论

如果这不是批处理的一个 bug 的话,可以大胆的猜测一下。回顾一下 例4,“:来瓶啤酒” 是复合语句块的最后一句,此后该语句块中就没有语句了,如果此时有一个goto语句跳转过来,那么系统将无法识别下一句究竟是哪个而导致混乱,为避免这种情况的发生,系统就设定了这么一个错误。

至于 “::” 的情况,其实也是一个道理,系统只知道它是一个标签而不进行处理,其它的“难题”都交给goto。

^ 分行

set val=value1 value2^
        value3 value4
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注