如何向批处理文件传递参数

如何向批处理文件传递参数

技术背景

在批处理编程中,向批处理文件传递参数是一项常见需求。通过传递参数,可以让批处理文件根据不同的输入执行不同的操作,提高批处理文件的灵活性和复用性。

实现步骤

基本参数传递

在批处理文件中,可以使用 %1%2%3 等表示传递的第 1、2、3 个参数,最多可传递 9 个参数。例如:

1
2
3
@echo off
echo %1
echo %2

运行该批处理文件时,输入:

1
C:\> script.bat Hello World

输出结果为:

1
2
Hello
World

处理所有参数

使用 %* 可以表示所有传递的参数。例如:

1
2
3
4
5
6
@echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*

当运行 test-command admin password foo bar 时,上述批处理文件将执行 fake-command /u admin /p password admin password foo bar

处理缺失参数

可以使用 IF 语句来智能处理缺失的参数。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off
IF %1.==. GOTO No1
IF %2.==. GOTO No2
REM 执行操作
GOTO End1

:No1
ECHO No param 1
GOTO End1
:No2
ECHO No param 2
GOTO End1

:End1

处理复杂参数

对于包含特殊字符的复杂参数,直接使用 %1 等可能会出错。可以通过将参数输出到临时文件,再从文件中读取的方式解决。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
set "prompt="
echo on
for %%b in (1) do rem * #%1#
@echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

循环处理参数

可以使用 FOR 循环遍历所有参数。示例如下:

1
2
3
FOR %%A IN (%*) DO (
ECHO %%A
)

解析命名参数

下面是一个解析命名参数的示例:

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson

SET CMD=%~1

IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=

SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs

ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)

REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof

:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1

键值对参数传递

如果希望以键值对的方式传递参数,可以使用以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@echo off

setlocal enableDelayedExpansion

:::::: 分配参数为键值对 :::::::::::::
set counter=0
for %%# in (%*) do (
set /a counter=counter+1
set /a even=counter%%2

if !even! == 0 (
echo setting !prev! to %%#
set "!prev!=%%~#"
)
set "prev=%%~#"
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: 显示分配结果
echo %one% %two% %three% %four% %five%

endlocal

运行示例:

1
c:\>argumentsDemo.bat one 1 "two" 2 three 3 four 4 "five" 5

输出结果:

1
1 2 3 4 5

核心代码

简单参数传递示例

1
2
3
@echo off
echo Your name is: %1
echo Your age is: %2

复杂参数处理示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
set "prompt="
echo on
for %%b in (1) do rem * #%1#
@echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

解析命名参数示例

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson

SET CMD=%~1

IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=

SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs

ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)

REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof

:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1

最佳实践

  • 使用 SETLOCAL 避免变量影响调用环境。
  • 初始化变量,防止调用环境中已定义的变量影响程序。
  • 使用 %~1 去除参数的引号。
  • 谨慎使用 SHIFT,确保在使用参数时正确移动参数位置。
  • 对于可能包含特殊字符的参数,采用临时文件等方式处理。

常见问题

参数中包含特殊字符

直接使用 %1 等处理包含特殊字符的参数可能会导致语法错误。可以通过临时文件等方式解决。

参数数量限制

批处理文件最多可直接使用 %1%9 表示 9 个参数。如果需要处理更多参数,可以使用 %* 结合循环处理。

变量延迟扩展问题

在使用 FOR 循环和 IF 语句时,可能需要启用延迟扩展(setlocal enableDelayedExpansion),使用 !变量名! 来引用变量。

引号处理问题

使用 %~1 可以去除参数的引号,但在判断参数是否为空时,应使用 IF "%ARG%" == "" 而不是 IF [%ARG%] == [],因为 [] 与以空格结尾的值不兼容。


如何向批处理文件传递参数
https://119291.xyz/posts/how-to-pass-arguments-to-a-batch-file/
作者
ww
发布于
2025年7月16日
许可协议