基本语法
变量定义与使用
在 cmd 中,要设置一个变量,可以使用 set
命令,语法如下:
1 | set 变量名=变量值 |
例如,要设置变量名为 my_var
的变量,值为 hello world
,可以这样写:
1 | set my_var=hello world |
要使用这个变量,可以使用 %
符号将变量名包含起来,例如:
1 | echo %my_var% |
这会输出变量 my_var
的值 hello world
。可以在需要使用这个变量的地方使用 %my_var%
代表该变量的值。
创建文件夹
1 | IF NOT EXIST "_dist" mkdir "_dist" |
移动文件或文件夹
1 | move "z-wiki" "_dist/" |
复制文件
这个只会复制一层
1 | copy "web" "_dist/" |
复制文件夹
1 | xcopy /e /i "web" %TARGET_DIR_PATH%web |
注意
后面也要写文件夹名,否则不会创建文件夹
调用子程序
默认BAT调用程序,程序退出,BAT不会继续执行,会退出。
使用call调用就会继续执行。
1 | call npm run build |
不打印日志
1 | call npm run build > NUL |
查找字符串
方式1
1 | @echo off |
方式2
1 | @echo off |
for循环中
在for循环中 方式1依旧生效
1 | @echo off |
方式2则需要改成如下才能生效
1 | @echo off |
加setlocal EnableDelayedExpansion
到脚本的开头,然后使用!errorlevel!
而不是%errorlevel%
注意
延迟扩展将导致变量在执行时扩展 时间而不是解析时间
延迟变量
1 | setlocal EnableDelayedExpansion |
设置本地为延迟扩展。其实也就是:延迟变量,全称延迟环境变量扩展, 想进阶,变量延迟是必过的一关!所以这一部分希望你能认真看。
为了更好的说明问题,我们先引入一个例子。
例1:
1 | @echo off |
结果:4
解说:为什么是4而不是5呢?在echo之前明明已经把变量a的值改成5了?
让我们先了解一下批处理运行命令的机制:
批处理读取命令时是按行读取的(另外例如for命令等,其后用一对圆括号闭合的所有语句也当作一行),在处理之前要完成必要的预处理工作,这其中就包括对该行命令中的变量赋值。
我们现在分析一下例1,批处理在运行到这句set a=5&echo %a%
之前,先把这一句整句读取并做了预处理——对变量a赋了值,那么%a%当然就是4了!(没有为什么,批处理就是这样做的。)
而为了能够感知环境变量的动态变化,批处理设计了变量延迟。
简单来说,在读取了一条完整的语句之后,不立即对该行的变量赋值,而会在某个单条语句执行之前再进行赋值,也就是说延迟
了对变量的赋值。
例2:
1 | @echo off |
解说:由于启动了变量延迟,得到了正确答案。变量延迟的启动语句是setlocal enabledelayedexpansion
,并且变量要用一对叹号“!!
”括起来(注意要用英文的叹号),否则就没有变量延迟的效果。
分析一下例2,首先setlocal enabledelayedexpansion
开启变量延迟,然后set a=4
先给变量a赋值为4,set a=5&echo !a!
这句是给变量a赋值为5并输出(由于启动了变量延迟,所以批处理能够感知到动态变化,即不是先给该行变量赋值,而是在运行过程中给变量赋值,因此此时a的值就是5了)。
for循环
1 | @echo off |
结果:12345
解说:本例开启了变量延迟并用!!
将变量扩起来,因此得到我们预期的结果。
如果不用变量延迟会出现什么结果呢?
结果是这样的:
ECHO 处于关闭状态。ECHO 处于关闭状态。ECHO 处于关闭状态。ECHO 处于关闭状态。ECHO 处于关闭状态。
即没有感知到for语句中的动态变化。
写入文件
基本用法
1 | echo 123>test.txt |
追加写入
1 | echo 123>>test.txt |
写入并追加
1 | echo #!/bin/bash>test.sh |
如果字符串中有表达式,我们需要这样写
1 | echo "echo 123">test.txt |
这样虽然能正常写入了,但是写入的文本内容也会被加上双引号,如下
1 | "echo 123" |
但是上面的写法最后都会自动添加换行或者有双引号
要想不换行可以这样写
如果文本内容中包含空格或特殊字符,需要使用双引号括起来,可以在echo后面加上 set /p 切换到提示模式来避免直接输出双引号:
1 | <nul set /p =" hello word:">test.txt |
这样虽然不换行 也没有双引号了,但是前面的空格也被去掉了。
删除文件
只会删除文件,不会删除文件夹
1 | del %cd%\public\* /s /q |
其中
%cd%
是当前目录。/s
删除文件和子文件夹下的文件。/q
静默删除,不提醒。
删除文件夹下的文件和文件夹,不删除当前文件夹
1 | del %cd%\public /s /q |
删除文件夹
这个命令只能删除文件夹 后边传的路径只能是文件夹路径
1 | rd /S /Q %cd%\public |
其中
%cd%
是当前目录。/S
rd命令只能删除空文件夹,添加\S
才能删除非空文件夹。/Q
静默删除,不提醒。
常见问题
注意一个大坑
在使用Bat生成sh文件的时候
注意下面一个示例
1 | echo #!/bin/sh >test.sh |
这么一个简单的脚本在服务器上运行的时候竟然无法运行
原因竟然是执行的命令最后的符号是\r
,导致命令无法执行。
解决方法很简单
命令后面添加一个空格就行了,这个问题排查了很长时间,网上也没找到解决方案。
如果最终我们运行的是一个类的话,也会提示
无法找到或加载主类
,就很离谱。
修改后的如下
1 | echo #!/bin/sh >test.sh |
GO项目一键打包
build_linux64.bat
1 | @echo off |
一键拉取代码
如果我们的项目比较多,需要一个一个更新代码,我们只能一个目录进入来pull,太麻烦了,这里提供一个一键拉取代码的脚本。
支持当前同级目录项目及子目录项目的拉取更新。
pull_batch.bat
1 | @echo off |
这样把该文件放在项目文件夹下,双击运行即可。