windows batch script小结

目录

本文是关于windows batch script的简单小结,便于个人快速参考。

主要参考来源:

变量

  • %variable_name%: 在运行前会被替换为实际的值,和Linux不同,batch script的变量大小写不敏感
  • %n for 0 <= n <= 9,%0指batch file本身的名称,%1-%9指传给batch file的位置参数(仅 batch file 中适用 )
  • %* 从除batch file name以外的所有参数(仅 batch file 中适用 )

如果传入batch file的参数是一个文件名,还可以通过一系列符号获取各种文件属性 可用SHIFT和GOTO遍历输入参数

特殊变量

以下是一些windows预设的只读系统变量

  • %CD% - 当前目录,类似linux中的pwd
  • %TIME% - 当前系统时间 HH:MM:SS.mm
  • %DATE% - 当前日期,根据本地系统设置的格式显示
  • %RANDOM% - 0到32767的随机数
  • %ERRORLEVEL% - 上一条命令或脚本执行的返回值
  • %USERNAME% - 当前用户名

更多请查看文档

引号与转义 ( Quoting and escaping )

^放在特殊字符前面,比如<,>,|,&,^, 可以实现转义

echo on 和 off

默认每条命令都会被先打印再执行,除非在batch file开头加上@echo off

代码注释

以REM开头的整行comment,或以&REM结尾的inline comment
冒号也可以做为注释,但可读性差而且容易出错,不建议使用

多行命令

^放在行尾,可分隔单条长命令为多行

操作符(运算 / 比较 / 逻辑)

  • 数学运算: +(加),-(减),*(乘),/(除),%(取模),
  • 比较: EQU(相等),NEQ(不相等),LSS(小于),LEQ(小于等于),GTR(大于),GEQ(大于等于)
  • 逻辑:NOT 除此之外还支持 -=,+=,/= 等类C的inplace assign操作符,以及&(位与),|(位或),^(异或)

命令结果传给变量

Batch没有直接的方式,只能通过for /f的形式:

for /f "delims=" %%i in ('command') do set var=%%i

更多细节见此Blog

字符串相关

  • 子串 substring
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
  • 替换 (replace )
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.
  • 包含判断 (contain/like,不支持含引号的情况) 如果a包含bc,则echo yes
if not "%a:bc=%"=="%a%" echo yes 
  • 开头判断 (start with)
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".

流程控制

条件判断

  • if 判断 (用 if /? 获取语法帮助) 语法:
exist <filename>
<string>==<string>
<expression1> equ <expression2> -- equals
<expression1> neq <expression2> -- not equal
<expression1> lss <expression2> -- less than
<expression1> leq <expression2> -- less than or equal
<expression1> gtr <expression2> -- greater than
<expression1> geq <expression2> -- greater than or equal
defined <variable>
errorlevel <number>
cmdextversion <number>

注意: 条件判断仅可以加上NOT,无法用 AND/OR 进行链接,只能通过嵌套IF ELSE 变通实现

例子:

if not 1 equ 0 echo Not equal
if 1 equ 0 echo A & echo B
	Does nothing; both echo commands are subject to the condition.
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
	Notice the brackets around the positive then-part to make it work.
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

FOR

FOR %variable IN (set) DO command [command-parameters]
FOR /D %variable IN (set) DO command [command-parameters] 
FOR /L %variable IN (start,step,end) DO command [command-parameters]
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
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中的变量名只能是单个字母,而且大小写敏感
  • 在interactive的命令行中用%x,在batch中用%%x,请注意不是%i%和%%i%%,要和正常的变量进行区分
  • FOR /D 遍历当前目录名
  • FOR /R 遍历当前目录名及子目录
  • FOR /L in (start, step, end) 遍历数字
  • FOR /F 可以遍历字符串,文件集合,以及命令执行的结果

参考例子和具体用法

GOTO

Batch中没有While循环,只能通过IF和GoTo某个语句标签来实现。
:EOF是一个虚拟标签,代表batch file的结尾,GOTO :EOF代表结束继续执行。

小结

windows batch批处理脚本功能真的非常有限,在项目环境严重受限的情况下,只能选择它。所以还是有必要去熟悉它的用法。它是windows预装的,不用安装第三方依赖,是OS的Shell,是调用其它更强大脚本和程序入口。

同样是OS的Shell,Linux的bash就比batch强大太多。所以很多人装了将bash带到windows的工具,最方便的莫过于git for windows,将\usr\bin目录加入环境变量后就可以用到大多数bash的常用命令。若有条件,装个windows subsystem for linux也是另外一个选择。

不过后来微软开发了PowerShell,借助.Net和面向对象,易用性和功能都有了质的飞跃。但PowerShell通常还是要用batch file去调用。

https://tutorialreference.com/batch-scripting/batch-script-tutorial