windows批处理脚本相关概念

想自动化创建markdown文件时了解到的相关技术,利用AI进行了整理简单了解即可

批处理脚本(BAT)完整教程:语法、概念与实践

目录

  1. 基本概念

  2. 常用命令

  3. 变量系统

  4. 特殊参数扩展

  5. 命令行参数处理

  6. 特殊符号

  7. 控制结构

  8. 高级概念

  9. 实用脚本示例

基本概念

批处理脚本(.bat 或 .cmd 文件)是Windows系统下的脚本文件,包含一系列DOS命令,用于自动化执行任务。它是一种解释性语言,由命令提示符(cmd.exe)解释执行。

特点:

  • 无需编译,直接执行

  • 逐行解释执行

  • 可以调用系统命令和其他程序

  • 支持变量、条件判断和循环等基本编程结构

常用命令

文件操作

  • dir - 显示目录内容

  • cd - 改变当前目录

  • md/mkdir - 创建目录

  • rd/rmdir - 删除目录

  • copy - 复制文件

  • move - 移动文件

  • del - 删除文件

  • ren/rename - 重命名文件

系统操作

  • echo - 显示文本或关闭/打开命令回显

  • cls - 清空屏幕

  • type - 显示文件内容

  • date - 显示或设置日期

  • time - 显示或设置时间

  • ver - 显示Windows版本

  • title - 设置命令提示符窗口标题

程序执行

  • start - 启动一个新窗口执行程序

  • call - 调用另一个批处理文件

  • exit - 退出批处理程序

  • pause - 暂停程序执行,等待用户按键

变量系统

系统变量

变量 说明
%SystemRoot% Windows系统目录(通常是C:\Windows)
%SystemDrive% 系统所在驱动器(通常是C:)
%UserProfile% 当前用户的个人文件夹
%PATH% 可执行文件路径
%TEMP%/%TMP% 临时文件夹路径
%DATE% 当前日期
%TIME% 当前时间
%CD% 当前目录
%ALLUSERSPROFILE% 所有用户配置文件位置
%APPDATA% 应用程序数据存储位置
%CMDCMDLINE% 启动当前Cmd.exe的命令行
%CMDEXTVERSION% 命令处理程序扩展版本号
%COMPUTERNAME% 计算机名称
%COMSPEC% 命令行解释器可执行程序路径
%ERRORLEVEL% 上一条命令的错误代码
%HOMEDRIVE% 用户主目录所在驱动器
%HOMEPATH% 用户主目录完整路径
%HOMESHARE% 用户共享主目录的网络路径
%LOGONSERVER% 验证当前登录会话的域控制器名称
%NUMBER_OF_PROCESSORS% 安装的处理器数目
%OS% 操作系统名称
%PATHEXT% 操作系统认为可执行的文件扩展名列表
%PROCESSOR_ARCHITECTURE% 处理器芯片体系结构
%PROCESSOR_IDENTFIER% 处理器说明
%PROCESSOR_LEVEL% 处理器型号
%PROCESSOR_REVISION% 处理器版本号
%PROMPT% 当前命令提示符设置
%RANDOM% 0到32767之间的随机数
%USERDOMAIN% 包含用户帐户的域名称
%USERNAME% 当前登录用户名
%WINDIR% 操作系统目录位置

用户自定义变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off
set var=Hello World
echo %var%

:: 设置带空格的变量值
set "var=Hello World with spaces"
echo %var%

:: 数值计算
set /a num=10+5
echo %num%

:: 删除变量
set var=

特殊参数扩展

根据官方文档,批处理脚本提供了强大的参数扩展功能,使用%~语法可以对参数进行各种转换。

基础扩展修饰符

语法 说明
%~1 展开%1并删除周围的引号
%~f1 将%1扩展到完全限定的路径名
%~d1 仅将%1扩展为驱动器号
%~p1 仅将%1扩展到路径
%~n1 仅将%1扩展到文件名
%~x1 仅将%1扩展到文件扩展名
%~s1 扩展路径只包含短名称
%~a1 将%1扩展到文件属性
%~t1 将%1扩展到文件的日期和时间
%~z1 将%1扩展到文件的大小
%~$PATH:1 搜索PATH环境变量中的目录,将%1扩展到找到的第一个文件的完整路径

%~dp0详解

%~dp0是最常用的特殊扩展之一:

  • d = 驱动器号

  • p = 路径

  • 0 = 表示批处理文件本身

例如,如果批处理文件位于F:\Temp\Batch\test.bat,则:

1
2
3
4
echo %~dp0  :: 输出 F:\Temp\Batch\
echo %~f0 :: 输出 F:\Temp\Batch\test.bat
echo %~n0 :: 输出 test
echo %~x0 :: 输出 .bat

组合扩展示例

语法 说明
%~dp1 将%1扩展到驱动器号和路径
%~nx1 将%1扩展到文件名和扩展名
%~dp$PATH:1 在PATH中搜索%1,扩展到找到的第一个文件的驱动器号和路径
%~ftza1 将%1扩展为类似dir命令的输出行

命令行参数处理

基本参数访问

1
2
3
4
5
@echo off
echo 批处理文件名: %0
echo 第一个参数: %1
echo 第二个参数: %2
echo 第三个参数: %3

%*的含义

%*表示传递给批处理文件的所有参数(不包括%0),保留参数中的引号和空格。

1
2
@echo off
echo 所有参数: %*

处理超过9个参数

使用shift命令可以处理超过9个参数:

1
2
3
4
5
6
7
@echo off
:loop
if "%1"=="" goto end
echo 参数: %1
shift
goto loop
:end

参数解析示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@echo off
setlocal enabledelayedexpansion

set "source="
set "destination="
set "verbose=false"

:parse_args
if "%1"=="" goto end_parse
if "%1"=="/v" (
set "verbose=true"
shift
goto parse_args
)
if not defined source (
set "source=%1"
) else if not defined destination (
set "destination=%1"
)
shift
goto parse_args

:end_parse
echo 源: %source%
echo 目标: %destination%
echo 详细模式: %verbose%
endlocal

特殊符号

重定向符号

  • > - 输出重定向(覆盖文件)

  • >> - 输出重定向(追加到文件)

  • < - 输入重定向

  • | - 管道符号,将前一个命令的输出作为后一个命令的输入

通配符

  • * - 匹配任意字符序列

  • ? - 匹配任意单个字符

其他符号

  • @ - 隐藏命令本身的显示

  • : - 标签定义

  • :: - 注释(与rem类似,但执行更快)

  • & - 命令分隔符,在同一行执行多个命令

  • && - 逻辑与,前一个命令成功才执行后一个

  • || - 逻辑或,前一个命令失败才执行后一个

  • () - 命令块,将多个命令作为一个整体执行

  • ^ - 转义字符,用于显示特殊字符本身

高级重定向示例

1
2
3
4
5
6
7
8
@echo off
:: 将命令输出同时保存到文件和显示在屏幕上
dir | tee output.txt

:: 错误重定向
command 2> error.log :: 将错误输出到文件
command 2>&1 :: 将错误输出重定向到标准输出
command > output.log 2>&1 :: 将所有输出重定向到文件

控制结构

if 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@echo off
set var=10

:: 基本if语句
if %var% equ 10 (
echo 变量等于10
)

:: if-else语句
if %var% gtr 5 (
echo 变量大于5
) else (
echo 变量小于等于5
)

:: 文件/目录检查
if exist "file.txt" (
echo 文件存在
)

if not exist "folder" (
mkdir "folder"
)

:: 字符串比较
if "string1"=="string2" (
echo 字符串相等
)

for 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@echo off
:: 遍历文件
for %%f in (*.txt) do (
echo 文件: %%f
)

:: 遍历目录
for /d %%d in (*) do (
echo 目录: %%d
)

:: 遍历数字序列
for /l %%i in (1,1,5) do (
echo 数字: %%i
)

:: 遍历命令输出
for /f "delims=" %%a in ('dir /b *.txt') do (
echo 文件: %%a
)

:: 遍历文件内容
for /f "tokens=1,2 delims=," %%a in (data.csv) do (
echo 列1: %%a, 列2: %%b
)

goto 语句和标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off
echo 开始
goto middle

:start
echo 这是开始标签
goto end

:middle
echo 这是中间标签
goto start

:end
echo 这是结束标签

call 语句

1
2
3
4
5
6
7
8
9
10
@echo off
call :subroutine "Hello World"
goto end

:subroutine
echo 接收到的参数: %1
exit /b :: 返回主程序

:end
echo 主程序结束

高级概念

延迟变量扩展

延迟变量扩展允许在代码块中更新和使用变量:

1
2
3
4
5
6
7
8
9
@echo off
setlocal enabledelayedexpansion
set count=0
for %%i in (*.txt) do (
set /a count+=1
echo !count!: %%i :: 使用!而非%来访问延迟扩展变量
)
echo 总共有 !count! 个txt文件
endlocal

错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@echo off
:: 检查命令执行结果
copy file1.txt file2.txt
if %ERRORLEVEL% equ 0 (
echo 复制成功
) else (
echo 复制失败,错误代码: %ERRORLEVEL%
)

:: 使用条件执行符号
copy file1.txt file2.txt && echo 复制成功 || echo 复制失败

:: 设置错误级别
@echo off
if "%1"=="" (
echo 参数缺失
exit /b 1 :: 设置错误级别为1
)
echo 参数: %1
exit /b 0 :: 设置错误级别为0

环境变量操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@echo off
:: 显示所有环境变量
set

:: 设置临时环境变量
set temp_var=临时值
echo %temp_var%

:: 永久设置环境变量(需要管理员权限)
setx permanent_var "永久值"

:: 读取注册表中的环境变量
for /f "skip=2 tokens=3*" %%a in ('reg query "HKCU\Environment" /v PATH') do (
echo 当前用户PATH: %%a %%b
)

数组

虽然批处理不直接支持数组,但可以模拟数组功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@echo off
setlocal enabledelayedexpansion

:: 定义数组
set arr[0]=第一个元素
set arr[1]=第二个元素
set arr[2]=第三个元素

:: 访问数组元素
echo %arr[0]%
echo %arr[1]%
echo %arr[2]%

:: 遍历数组
for /l %%i in (0,1,2) do (
echo !arr[%%i]!
)

:: 获取数组长度
set "array_length=0"
:count_loop
if defined arr[%array_length%] (
set /a array_length+=1
goto count_loop
)
echo 数组长度: %array_length%

endlocal

字符串操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@echo off
setlocal enabledelayedexpansion

:: 字符串连接
set str1=Hello
set str2=World
set combined=%str1% %str2%
echo %combined%

:: 字符串长度
set test_str=This is a test string
set "len=0"
:len_loop
if "!test_str:~%len%!" neq "" (
set /a len+=1
goto len_loop
)
echo 字符串长度: %len%

:: 字符串截取
set full_str=Hello World
echo 前5个字符: %full_str:~0,5%
echo 从第6个字符开始: %full_str:~5%
echo 最后5个字符: %full_str:~-5%

:: 字符串替换
set original=Hello World
set replaced=%original:World=Batch%
echo %replaced%

endlocal

实用脚本示例

文件备份脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@echo off
setlocal enabledelayedexpansion

:: 设置备份参数
set "source=C:\Data"
set "backup_root=D:\Backup"
set "backup_folder=%backup_root%\%DATE:/=-%_%TIME::=-%"
set "log_file=%backup_root%\backup.log"

:: 创建备份目录
mkdir "%backup_folder%" >nul 2>&1

:: 开始备份
echo ======================================== >> "%log_file%"
echo 备份开始: %DATE% %TIME% >> "%log_file%"
echo 源目录: %source% >> "%log_file%"
echo 备份目录: %backup_folder% >> "%log_file%"

:: 执行备份
xcopy "%source%" "%backup_folder%" /E /H /R /Y /Z >> "%log_file%" 2>&1

:: 检查备份结果
if %ERRORLEVEL% equ 0 (
echo 备份成功完成 >> "%log_file%"
echo 备份文件已保存到: %backup_folder%
echo 日志文件: %log_file%
) else (
echo 备份失败 >> "%log_file%"
echo 备份过程中发生错误,请查看日志文件: %log_file%
exit /b 1
)

echo 备份结束: %DATE% %TIME% >> "%log_file%"
echo ======================================== >> "%log_file%"

:: 清理旧备份(保留最近7天)
forfiles /p "%backup_root%" /s /m * /d -7 /c "cmd /c if @isdir==TRUE rmdir /s /q @path" >> "%log_file%" 2>&1

endlocal
pause

系统信息收集脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@echo off
setlocal enabledelayedexpansion

set "report_file=system_info_%DATE:/=-%_%TIME::=-%.txt"

:: 收集系统信息
echo 系统信息报告 > "%report_file%"
echo ======================== >> "%report_file%"
echo 生成时间: %DATE% %TIME% >> "%report_file%"
echo ======================== >> "%report_file%"
echo. >> "%report_file%"

echo 【操作系统信息】 >> "%report_file%"
ver >> "%report_file%"
echo 操作系统: %OS% >> "%report_file%"
echo 系统目录: %SystemRoot% >> "%report_file%"
echo. >> "%report_file%"

echo 【硬件信息】 >> "%report_file%"
echo 计算机名称: %COMPUTERNAME% >> "%report_file%"
echo 处理器架构: %PROCESSOR_ARCHITECTURE% >> "%report_file%"
echo 处理器型号: %PROCESSOR_IDENTFIER% >> "%report_file%"
echo 处理器数量: %NUMBER_OF_PROCESSORS% >> "%report_file%"
echo. >> "%report_file%"

echo 【内存信息】 >> "%report_file%"
systeminfo | findstr /C:"Total Physical Memory" >> "%report_file%"
systeminfo | findstr /C:"Available Physical Memory" >> "%report_file%"
echo. >> "%report_file%"

echo 【磁盘信息】 >> "%report_file%"
wmic logicaldisk get caption,size,freespace >> "%report_file%"
echo. >> "%report_file%"

echo 【用户信息】 >> "%report_file%"
echo 当前用户: %USERNAME% >> "%report_file%"
echo 用户域: %USERDOMAIN% >> "%report_file%"
echo 用户配置文件: %USERPROFILE% >> "%report_file%"
echo. >> "%report_file%"

echo 【网络信息】 >> "%report_file%"
ipconfig /all | findstr /C:"IPv4 Address" /C:"Subnet Mask" /C:"Default Gateway" >> "%report_file%"
echo. >> "%report_file%"

echo 【环境变量】 >> "%report_file%"
echo PATH: %PATH% >> "%report_file%"
echo. >> "%report_file%"

echo 报告已生成: %report_file%
start notepad "%report_file%"

endlocal
pause

文件批量重命名脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@echo off
setlocal enabledelayedexpansion

if "%1"=="" (
echo 用法: %0 [文件类型] [前缀]
echo 示例: %0 .txt "文档_"
exit /b 1
)

set "file_type=%1"
set "prefix=%2"
set "count=1"

echo 开始重命名%file_type%文件...
echo 前缀: %prefix%

for /f "delims=" %%f in ('dir /b /a-d /o:n *%file_type%') do (
set "extension=%%~xf"
set "new_name=%prefix%!count!!extension!"

echo "%%f" -^> "!new_name!"
ren "%%f" "!new_name!"

set /a count+=1
)

echo 重命名完成,共处理了 %count% 个文件

endlocal
pause

批量文件处理脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@echo off
setlocal enabledelayedexpansion

:: 检查参数
if "%1"=="" (
echo 用法: %0 [源目录] [目标目录]
exit /b 1
)

set "source_dir=%1"
set "dest_dir=%2"

:: 创建目标目录
if not exist "%dest_dir%" (
mkdir "%dest_dir%"
echo 创建目标目录: %dest_dir%
)

:: 处理所有txt文件
set "count=0"
for /r "%source_dir%" %%f in (*.txt) do (
set /a count+=1

:: 获取文件名和路径
set "file_name=%%~nxf"
set "file_path=%%~dpFf"

:: 复制文件
copy "%%f" "%dest_dir%\!file_name!" >nul

:: 显示进度
echo 处理文件 !count!: !file_name!
)

echo 处理完成,共复制了 %count% 个文件

endlocal
pause

这个完整的批处理脚本教程涵盖了从基础概念到高级技巧的所有内容,包括特殊变量扩展、参数处理、控制结构和实用脚本示例。掌握这些知识可以帮助你创建强大的自动化脚本,提高工作效率。