bat基本操作
bat操作
::采用ANSI编码或UTF-8强制设置
@echo off
chcp 65001
set dd=%date%
set tt=%time%
::取星期:
echo %dd:~10,6%
set tt1=%dd:~0,4%%dd:~5,2%%dd:~8,2%-%tt:~0,2%%tt:~3,2%%tt:~6,2%%tt:~9,2%
::时间格式20091710
set hour=%time:~,2%
if "%time:~,1%"==" " set hour=0%time:~1,1%
set anotherVariable=%date:~5,2%%date:~8,2%%date:~11,2%%hour%
::空格替换为0
set "tt1=%tt1: =0%"
copy e:\\bigFile.txt e:\\copyfile%tt1%.txt
copy e:\\bigFile.txt d:\\copyfile.txt
::强制 所有子目录 不确认删除文件
del /f /s /q e:\copyfile%tt1%.txt
del /f /s /q d:\copyfile.txt
::删除文件夹
if exist D:\EFI\Temp( rd /s /q D:\EFI\Temp)
echo 生成时间戳验证码
call TimeStampVerificationCode.bat
::目录相关
echo 当前盘符: %~d0
echo 当前目录: %~dp0
set batdir=%~dp0
echo 当前盘符和路径的短文件名格式: %~sdp0
echo 当前批处理文件绝对路径: %~f0
echo 当前CMD默认目录: %cd%
::上一级目录路径
echo 当前目录: %cd%
cd..
echo 上一级目录路径是: %cd%
::上一级目录名称这个有的地方好用有的会返回上级目录路径
echo 当前目录: %cd%
if %cd%==%cd:~,3% echo 当前目录已经是%cd:~,1%盘的根目录!&goto end
cd..
set "bd=%cd%"
cd..
set "bbd=%cd%"
if "%bbd%"=="%bd%" (echo 上一级目录是: %cd:~,1%盘的根目录!
) else call echo 上一级目录是: "%%bd:%bbd%\=%%"
:end
::当前盘符
echo 当前盘符: %cd:~,1%
::根目录
echo 根目录: %cd:~,3%
::常用系统路径变量
echo 当前启动的系统的所在分区: %SYSTEMDRIVE%
echo 当前启动的系统的所在目录: %WINDIR%
echo 当前用户TEMP缓存变量: %TEMP%
echo 当前用户数据变量: %USERPROFILE%
echo 当前用户环境变量: %HOMEPATH%
echo 程序安装目录: %PROGRAMFILES%
echo 默认应用程序存储数据的位置:%APPDATA%
echo 启动当前的Cmd.exe的命令行: %CMDCMDLINE%
echo 操作系统的名称: %OS%
echo 可执行的文件扩展名的列表: %PATHEXT%
::循环
for /l %%i in (1 1 3) do (
echo %%i
call %batdir%TimeStampVerificationCode.bat
ping -n 2 127.0.0.1>nul
)
pause
echo 时间间隔(100ms级别)
set time_begin=%time%
set /A time_begin_minute=%time_begin:~3,2%
set /A time_begin_second=%time_begin:~-5,2%
set /A time_begin_millisec=%time_begin:~-2,2%
::其他脚本
set time_end=%time%
set /A time_end_minute=%time_end:~3,2%
set /A time_end_second=%time_end:~-5,2%
set /A time_end_millisec=%time_end:~-2,2%
if %time_end_millisec% lss %time_begin_millisec% set /A time_end_millisec+=100&set /A time_end_second-=1
if %time_end_second% lss %time_begin_second% set /A time_end_second+=60&set /A time_end_minute-=1
set /A minute=time_end_minute-time_begin_minute
set /A second=time_end_second-time_begin_second
set /A millisec=time_end_millisec-time_begin_millisec
echo 运行结束!.........(%time_begin%-%time_end%)耗时:!minute!分!second!秒!millisec!0毫秒
bat传递参数
@echo off
::%~1 第一个参数,除去双引号
echo %~0
echo arg1:%~1
echo arg2:%~2
pause
整行替换
::关闭显示并启用变量延迟,启用本地变量
@echo off&setlocal EnableDelayedExpansion
chcp 65001
set rootPath=E:\Src
echo.
set srcFile=%rootPath%\***.xml
set anotherVariable=logo.ico
echo !srcFile!更新图标:!anotherVariable!
(for /F "delims=" %%a in (%srcFile%) do (
set "line=%%a"
set "newLine=!line:ApplicationIcon>=!"
if "!newLine!" neq "!line!" (
set "newLine= <ApplicationIcon>%anotherVariable%</ApplicationIcon>"
)
echo !newLine!
)) > 111.tmp
move /y 111.tmp !srcFile!
setlocal DisableDelayedExpansion
pause
指定字符串替换
::关闭显示并启用变量延迟,启用本地变量
@echo off&setlocal EnableDelayedExpansion
chcp 65001
set rootPath=E:\Src
echo.
set srcFile=%rootPath%\App.config
echo App.config更新信息:add key="Servers" value="10.100.10.85,www.baidu.com,www.cnblogs.com"
sed -i 's/add key=\x22Servers\x22 value=\x22www.baidu.com,10.100.10.85,www.cnblogs.com\x22/add key=\x22Servers\x22 value=\x2210.100.10.85,www.baidu.com,www.cnblogs.com\x22/g' !srcFile!
sed -i 's/add key=\x22Servers\x22 value=\x22www.baidu.com,www.cnblogs.com,10.100.10.85\x22/add key=\x22Servers\x22 value=\x2210.100.10.85,www.baidu.com,www.cnblogs.com\x22/g' !srcFile!
setlocal DisableDelayedExpansion
pause
使用 sed.exe,依赖 msys-2.0.dll
FOR语句
依次处理每个元素,直到所有的元素都被处理为止。一般规则如下:
for /f "eol=; skip=3 delims=, tokens=1,* usebackq" %%i in (command1) do command2
/f | eol | skip | delims | tokens | usebackq |
---|---|---|---|---|---|
以行为单位处理文本文 | 忽略以指定字符打头的行 | 跳过无用的行 | 切分字符串 | 定点提取 | 增强型参数 |
一般语句 | 含参usebackq |
---|---|
for /f %%i in (文件名) do () | for /f "usebackq" %%i in ("文件名") do () |
for /f %%i in ('命令语句') do () | for /f "usebackq" %%i in (` 命令语句` ) do () |
for /f %%i in ("字符串") do () | for /f "usebackq" %%i in ('字符串') do () |
清空目录文件
删除各项目的bin/obj文件夹
echo %cd%
echo.
echo start clearing...
echo.
::delete specify folder(obj,bin)
for /f "tokens=*" %%a in ('dir obj /b /ad /s ^|sort') do (
echo "%%a"
echo.
rd "%%a" /s/q
)
for /f "tokens=*" %%a in ('dir bin /b /ad /s ^|sort') do (
echo "%%a"
echo.
rd "%%a" /s/q
)
变量延迟
批处理的执行过程是“自上而下,逐条执行”。“逐条”并不等同于“逐行”。这个“条”,是“一条完整的语句”的意思,并不是指“一行代码”。什么样的语句才算“一条完整的语句”呢?
- 复合语句,整个复合语句是一条完整的语句,常见的复合语句有:for,if else,用连接符&、||和&&连接的语句,用管道符号|连接的语句,用括号括起来的,由多条语句组合而成的语句块。
- 非复合语句,如果该语句占据了一行的位置,则该行代码为一条完整的语句。
预处理机制,在代码“逐条”执行的过程中,cmd.exe 这个批处理解释器会对每条语句做一些预处理工作:
首先,把一条完整的语句读入内存中(不管这条语句有多少行,它们都会被一起读入),然后,识别出哪些部分是命令关键字,哪些是开关、哪些是参数,哪些是变量引用......
如果代码语法有误,则给出错误提示或退出批处理环境;如果顺利通过,接下来,就把该条语句中所有被引用的变量及变量两边的百分号对,用这条语句被读入内存之前就已经赋予该变量的具体值来替换......
当所有的预处理工作完成之后,批处理才会执行每条完整语句内部每个命令的原有功能。也就是说,如果命令语句中含有变量引用(变量及紧邻它左右的百分号对),并且某个变量的值在命令的执行过程中被改变了,即使该条语句内部的其他地方也用到了这个变量,也不会用最新的值去替换它们,因为某条语句在被预处理的时候,所有的变量引用都已经被替换成字符串常量了,变量值在复合语句内部被改变,不会影响到语句内部的其他任何地方。
预处理使用了变量扩展,用具体的值去替换被引用的变量及紧贴在它左右的那对百分号。我们可以使用变量延迟扩展语句,让变量的扩展行为延迟一下,使复合语句内部的变量实时感知到变量值的变化。
经常采用的方法是在适当位置使用 setlocal enabledelayedexpansion,该语句让变量成为局部变量,并延迟它的扩展行为;此时复合语句的语法有所变化:
复合语句 | 变量延迟 |
---|---|
%num% | !num! |
for /r 与 dir /ad /s
列举目录 | 优点 | 缺点 |
---|---|---|
for /r | 只通过 1 条语句就可以同时实现获取目录路径和处理目录路径的操作;遍历文件夹的时候,是边列举边处理的,获取到一条路径就处理一条路径,内存占用小,处理大量路径的时候不会产生停顿感; | 不能获取到带隐藏属性的目录,会产生遗漏;不能获取带指定属性的目录; |
dir /ad /s | 能一次性获取带任意属性的目录,不会产生遗漏; 能通过指定不同的参数获取带任意属性的目录,更具灵活性; | 仅能获取到目录路径;for /f 语句之后,需要先列举完所有的路径放入内存之后,才能对每一条路径进行进一步的处理,处理大量路径时,内存占用量偏大,并且在前期会产生明显的停顿感,用户体验度不够好; |
- 若仅仅是为了获取某文件夹及其所有子文件夹的路径的话,可使用 dir /ad /b /s 语句;
- 若需要过滤带隐藏属性的文件夹的话,for /r 和 dir 语句都可以实现,但 for /r 内存占用小,处理速度快;
- 若需要获取所有文件夹,则除了 dir /ad /b /s 外,别无选择,因为 for /r语句会遗漏带隐藏属性的文件夹;
for /d
匹配第一层目录。它仅能匹配当前目录下的第一级文件夹,或是指定位置上的文件夹,而不能匹配更深层次的子文件夹。
for /l
for /l %%i in (x,y,z) do (......)
计数循环。当循环次数确定的时候,选择此语句。当循环次数不确定的时候,用 goto 语句,要用 if 之类的条件语句来判断何时结束 goto 跳转。
统计脚本耗时
set time_begin=%time%
set /A time_begin_minute=%time_begin:~3,2%
set /A time_begin_second=%time_begin:~-5,2%
set /A time_begin_millisec=%time_begin:~-2,2%
::其他脚本
set time_end=%time%
set /A time_end_minute=%time_end:~3,2%
set /A time_end_second=%time_end:~-5,2%
set /A time_end_millisec=%time_end:~-2,2%
if %time_end_millisec% lss %time_begin_millisec% set /A time_end_millisec+=100&set /A time_end_second-=1
if %time_end_second% lss %time_begin_second% set /A time_end_second+=60&set /A time_end_minute-=1
set /A minute=time_end_minute-time_begin_minute
set /A second=time_end_second-time_begin_second
set /A millisec=time_end_millisec-time_begin_millisec
echo 执行成功!.........(%time_begin%-%time_end%)耗时:!minute!分!second!秒!millisec!0毫秒
bat获取exe输出值
cd /d **\Debug
BatHelper.exe CreateVersionInfo>result.txt
set result=0
:: 读取首行数据
for /f "delims=" %%i in (result.txt) do (
set /a revision=%%i& goto _ExitForLoop
)
:_ExitForLoop
del result.txt
echo !result!
cd "%~dp0"
namespace BatHelper.Program
static void Main(string[] args)
{
if (args.Length > 0)
{
string methodName = args[0];
InvokeStaticMethod(typeof(Program), methodName, args.Skip(1).ToArray());
}
}
// 创建版本信息(形如:35509)
static void CreateVersionInfo()
{
var dt = DateTime.Now;
var rslt = $"{dt.DayOfYear}{dt:HH}";
Console.WriteLine(rslt);
}
打开目录
%SystemRoot%\explorer.exe "%dir%"\bin