http://www.bathome.net/
隐藏CMD运行窗口

特殊符号

symbolfunction
.在一般命令中当作空格, 在echo命令中当作空行
^字符画某个符号,如: echo ^>
&组合命令,前后没有因果关系;只是为了写在一行; 注意:左侧不要有空格(会被左侧理解成1个字符),右侧空格无所谓!
&&短路特性.前一个执行成功,才执行后面
||前一个执行失败,才执行后面的命令; |表管道
1>nul将语句产生的输出信息屏蔽(或>nul);
2>nul将语句产生的错误信息屏蔽

基本变量

cmd自上而下、逐条处理批处理语句,注意:以下算作1条语句: for if else & || && | ()
这很类似于宏展开,需要延后这种行为?: setlocal EnableDelayedExpansion

举个栗子(::可注释,不过此处的code渲染引擎不支持,不再解释):

rem set
rem https://www.hanselman.com/blog/a-better-prompt-for-cmdexe-or-cool-prompt-environment-variables-and-a-nice-transparent-multiprompt
rem set不加任何选项给变量赋值默认就是字符串且空格无需引号!
rem setlocal enlocal 可以框定某个变量的范围,可以最多嵌套32层!
set /p m=1,n=2
rem 使用用户输入的值赋值给变量a; 可以模拟强制echo不换行!
set /p a="" <nul

rem 算术运算支持大多数操作: () + - * / % ! ~ & ^ | , >> <<  += -= *= /= %= <<= >>=
rem /a表后面是个表达式,等价于a=!a!+1
set /a a+=1

rem 默认就是"/c yn"
choice /t 8 /d n /m "Reboot?"
if %errorlevel% == 1 echo you input y!

字符串处理

注意
  • echo批处理的变量必须使用%a%形式, 而在for中必须使用%%i形式
  • echo后面多数符号会被当做字符输出,但以下除外(必须使用跳脱符^): & && | < >
  • echo后面跟这些字符时(& && | < >),不要再符号的左边留有空格,因为空格也会被当做一个字符echo
operatorfunction
%s:~0%截取所有字符
%s:~-5%截取最后5个字符
%s:~0,-5%截取第1-倒数第6个字符
%s:~-4,5%从倒数第4个字符开始,截取5个字符
%s:s1=s2%将s中字符串s1替换为s2并返回替换后的字符串;s2不写表示删除

基本语法

注意
  • 语句的边界即右圆括号)的上头不能加注释!!!
  • 小括号支持嵌套,但if语句内的新变量需要考虑延迟!!
  • 小括号中不要定义新变量,如果有任何变量赋值操作,请使用EnableDelayedExpansion+!var!代替!
  • for中的使用的%%i变量名只能是单个字符[a-zA-Z]!且是全局的!
  • 组合命令&左侧不要有空格(会被左侧理解成1个字符),右侧空格无所谓
  • windows服务区分大小写,命令/环境变量均不区分大小写
rem 注意:条件不支持逻辑运算符,需要的请使用个中间变量代替or,使用嵌套if代替and!
rem 只能使用'=='符号表示相等,'!='符号并无法表示不等!
rem 或者使用如下关键字: neq equ lss gtr leq geq
rem comamnd如果太多可以使用()分块处理
if %errorlevel% == 0 (
	rem ==号两边应该加上双引号,否则当左边变量为空或者被赋予特殊字符时,可能出错强行退出!
	if not "%var%"=="string2" (echo ok)
) else if exist "1.txt" (
	rem 判断OS位数,不区分大小写!或者判断'c:\Program Files (x86)'是否存在
	if /i "%PROCESSOR_IDENTIFIER:~0,3%" == "X86" (echo x86)
) else (
)
 
rem delims :默认是以Space和TAB键作为分隔符
rem tokens :默认只取第1列! tokens=*表示删除每行前面的空格并提取所有列!若*配合范围使用,前面也可以有,号!
rem 按空格(或,;=)分隔var,循环处理每个分隔,也可以使用通配符配合路径.
for %%i in (%var%) do command

rem [start,step,end]
for /l %%i in (1,1,5) do command

rem 搜索C盘所有exe文件. 注意:若不使用通配符,则必须判断是否存在,否则它会作假!
for /r d:/tmp %%i in (*.exe) do command

rem 注意:string时只能循环1次!!而且如果string中有叹号则将产生bug:如果最后1个是!号,则只能截取到第1个!号,否则叹号被过滤!
rem 如果未指定任何options则默认以空格分隔各列,并取所有列.一旦指定了delims则默认tokens=1.
rem 一旦指定了tokens则%%i与tokens个个域对应(下个域为%%j以此类推)!
for /f "options" %%i in (file|"string"|'cmd') do ...

rem 递归删除某些文件夹.注意:必须判断存在!!
for /d /r . %%d in (.svn .idea) do @if exist "%%d" echo delete "%%d" && rd /s /q "%%d"

rem 递归删除某种文件
for %%i in (c: d: e: f:) do (
    if exist %%i (cd /d %%i && del /s /f /q 1.txt* 2>nul)
)

rem 使用文件的方式删除指定的文件夹
dir /b /ad /s | find /i "Release" > out.txt
for /f %%i in (out.txt) do rd /s /q %%i >NUL 2>NUL

rem 逐行读取文件,忽略以#开头的行,跳过前两行,以','为分隔符,取第2,3,4,6-最后一列;
rem 下面这个列子%%i对应了第2列的内容,%%j对应了第3列的内容,%%l对应了第6列,%%m对应了*即余下的所有列!!
for /f "eol=# skip=2 delims=, tokens=2-4,6*" %%i in (text.txt) do echo %%i

rem 使用for循环处理字符串时,默认的分隔符不能符号化(^),故如果某个元素含有分隔符之能另辟蹊径!
setlocal EnableDelayedExpansion
set v=1;2 2
set d[0]=d1& set d[1]="d 2"
for /l %%i in (0 1 1) do (
  for /f "tokens=1* delims=;" %%a in ("!v!") do (
    call reg add "hkcu\Software\xxx" /v "%%a" /d %%d[%%i]%% /f
    set v=%%b
  )
)
endlocal

函数

  • 标签后最后不要加任何常规命令,所有函数均应该放在批处理文件末尾!
rem call :funname arg1 arg2... 参数在函数定义内为 %1 %2..
rem eof表函数体的结束(必须单独占用一行),返回call调用的地方继续执行* demos
:funname
COMMAND
goto :eof
	:last_folder
	if "%1%"=="" (
		goto :EOF
	)
	echo %1%
	shift
	goto :last_folder

rem sleep
rem xp以上支持'timeout <SECONDS>',如果想通用则应该使用:
rem 这将会延迟1s,192.0.2.x都是全球不存在的地址!
ping -n 1 -w 1000 192.0.2.2>nul
rem 将会延迟(5-1)秒.127.1也可以写成localhost.
ping -n 5 127.1>nul

颜色

rem 0黑色 1蓝色   2绿色   3湖蓝色   4红色   5紫色   6黄色  7白色
rem 8灰色 9淡蓝色 a淡绿色 b淡浅绿色 c淡红色  d淡紫色 e淡黄色 f亮白色
rem 第1个为背景色,第2个为前景色
color 03
rem -i 表示以交互模式运行
rem -d 表示不等待新的进程结束就返回
rem -s 表示以系统账户运行,具体看帮助

示例

  • 注意路径分割符必须使用反斜杠(反常识)!
rem 如果是xp
ver | find "5.">nul

rem 如果用户是Administrator
net user %username% | find "Administrators"

rem 文件搜索
set /p filename=输入要查找的文件名:
set alldrive=c d e f g h i j k l m n o p q r s t u v w x y z
for %%i in (%alldrive%) do if exist %%i:\ dir /s /b %%i: | find "%filename%" > results.txt
type results.txt & del results.txt & echo 搜索完毕

rem 获取u盘的盘符,3:所有硬盘的驱动器盘符,5:CD-ROM
@echo off & setlocal EnableDelayedExpansion
set DriveU=
for /f "skip=1 tokens=1 delims=" %%a in ('wmic logicaldisk where "drivetype='3'" get deviceid') do set DriveU=!DriveU!%%a
echo %DriveU%

rem 设置pagefile.sys位置,大小
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" /f /v PagingFiles /t REG_MULTI_SZ /d "%systemdrive%\\pagefile.sys 8196 8196"

rem 递归删除server开头的文件
@echo off
for /d %%i in (.) do (cd %%i
	del /s /f /q server*
)