http://steve-jansen.github.io/guides/windows-batch-scripting/part-1-getting-started.html
- 注释:REM 或 :: ,但是在 FOR 循环中使用 :: 可能会出错
REM This is a comment! :: This is a comment too!! (usually!)
- 关闭/打开批处理输出:
@ECHO OFF 关闭之后的批处理输出,@表示关闭此句命令的输出
ECHO ON 打开输出
- 输出一条消息
ECHO This is a message.
- 变量:未定义的变量,值为""(空串)
- 变量定义
SET foo=bar 注意,=左右不要有空格
SET /A foo=2+2 /A选项表示可以在赋值时使用数学计算
- 变量定义会覆盖已有的同名变量
- 不要将变量命名为和系统已经存在的常用变量相同的名字
- 读取变量(两边加%)
ECHO %foo%
- 列出所有已有的变量
SET
- 全部变量与局部变量
变量默认都是全局的,如果想使用局部变量,先调用一句
SETLOCAL
之后设置的变量为局部变量。局部变量会在
ENDLOCAL
之后全部清除,或者是在 EXIT 命令之后清除,或者是在当前脚本结束时清除。
- 命令行变量
%0 当前正在运行的批处理文件的路径,如果路径带空格,这个值会带双引号 %1 第1个参数 %9 第9个参数 %~0 同%0,去掉双引号 %~n0 同%~0,只有名字 更多请看下面解释
%~dp0 当前脚本的父目录
%~dp1 第1个参数所表示的文件的目录或目录的父目录(如果第1个参数不是个路径的话,那么就是当前所在的目录)
%~nx1 第1个参数的名字+扩展名(也是针对路径式的参数,如果参数不是路径那这么用就没有什么意义了)
SET me=%~n0
SET parent=%~dp0
- ~:去除引号
- d:drive
- p:path
- n:file name
- x:extension
- f:full name
- s:DOS 8.3风格的路径,例如C:PROGRA~1
- SHIFT指令
SHIFT 将命令行参数往左移一个,移完后,%1等同于移之前的%2
If判断文件是否存在
// 如果文件存在就打印YES IF EXISTS "x.bat" ( ECHO YES ) ELSE ( ECHO NO ) // 如果文件不存在就打印 do something IF NOT EXISTS "x.bat" ( ECHO do something )
- IF变量判断
// IF "%foo%"=="Qiucw" ( ECHO Yes, it's qiucw ) ELSE ( ECHO No, it's not qiucw )
IF NOT DEFINED name ( SET name=Qiucw ) ECHO %name%
// 命令扩展 SETLOCAL ENABLEEXTENSIONS
SET age=15 IF %age% EQU 15 ( )
- EQU - equal
- NEQ - not equal
- LSS - less than
- LEQ - less than or equal
- GTR - greater than
- GEQ - greater than or equal
- 循环
// 打印C盘所有文件 FOR %%i IN (C:*) DO ( @ECHO %%i )
- 返回值
- %ERRORLEVEL%可以取得最近运行的程序或脚本的返回值
- 系统自带的命令如ECHO,IF,SET不会影响这个值
IF %ERRORLEVEL% NEQ 0 ( )
- &&和||
// 此处:如果SomeCommand.exe返回值是0,则执行后面的命令 SomeCommand.exe && ECHO SomeCommand.exe succeeded! // 此处:如果SomeCommand.exe返回值不是0,则执行后面的命令 SomeCommand.exe || ECHO SomeCommand.exe failed with return code %ERRORLEVEL% // 此处,如果SomeCommand.exe返回值不是0,那么退出整个脚本(返回码1) SomeCommand.exe || EXIT /B 1
- 函数
- 函数要定义在脚本末尾
- 函数要以 EXIT /B 【ERRORCODE】返回给主逻辑
- 脚本主逻辑必须要以 EXIT /B 【ERRORCODE】 明确退出
@ECHO OFF SETLOCAL :: script global variables SET me=%~n0 SET log=%TEMP%\%me%.txt :: The "main" logic of the script IF EXIST "%log%" DELETE /Q %log% >NUL :: do something cool, then log it CALL :tee "%me%: Hello, world!" :: force execution to quit at the end of the "main" logic EXIT /B %ERRORLEVEL% :: a function to write to a log file and write to stdout :tee ECHO %* >> "%log%" ECHO %* EXIT /B 0
:tee函数注意点
- 用 %* 表示所有函数参数
- log 要追加而不是覆盖,所以用 >> 而不是 >
- log文件可能带空格,所以用 "%log%" 而不是 %log%
- 函数结果要用 EXIT /B 0
- Sleep
// 睡2秒 PING.EXE -N 2 127.0.0.1 > NUL
- stdin, stdout, stderr
数字代号:0代表标输入,1代码输出,2代表错误
// 把 DIR 的标准输出(stdout)重定向到 temp.txt(覆盖) DIR > temp.txt // 把 DIR 的标准输出(stdout)重定向到 temp.txt(追加) DIR >> temp.txt
// 把 DIR 的标准错误(stderr)重定向到 temp.txt(覆盖) DIR 2> temp.txt // 把 DIR 的标准错误(stderr)重定向到 temp.txt(追加) DIR 2>> temp.txt
// 把标准输出和标准错误合并 DIR SomeFile.txt 2>&1
// 合并并重定向 DIR SomeFile.txt > output.txt 2>&1
// 使用 SomeFile.txt 做为 SORT 的输入(注意这个有别于命令行参数) SORT < SomeFile.txt
一个程序的输出直接做为另一个程序的输入
// 例如,DIR 的输出直接做为 SORT 的输入 DIR /B | SORT
抛弃程序的输出
PING 127.0.0.1 > NULL
- 好玩
解释:CON 是 cmd 的 stdin,然后再把 TYPE 的 stdout 重定向到 output.txt……
有点不好理解,反正结果是,可以在命令行中输入文本,输入完成后按 Ctrl+Z 保存到 output.txt。