call 命令

本章节主要介绍 call 命令的使用:

CALL 命令基础

call 是一个功能强大的命令,它不但可在批处理程序中调用另一个批处理程序,而且还可调用指定标号处后面的所有命令(也可以称为子程序)。语法如下:

CALL [drive:][path]filename [batch-parameters]

参数说明:

  • [Drive:]   指定被调用批处理文件的盘符

  • [Path]   指定被调用批处理文件路径

  • FileName  指定被调用的批处理文件名,当被调用的批处理文件与正在执行的批处理文件都处于同一目录下时,可以省略盘符及路径;

  • batch-parameters   指定批处理程序所需的命令行参数信息;

  • /?  在命令提示符显示帮助;

实例:创建两个批处理文件,分别为 test.bat 和 sub.bat。在 test.bat 中调用 sub.bat,不传递任何参数信息。

(1)test.bat 文件内容:

@echo off
echo test.bat
call sub.bat
call C:\Users\Administrator\Desktop\sub.bat
pause

(2)sub.bat 文件内容:

@echo off
echo sub.bat

输出结果:

C:\Users\Administrator\Desktop> test.bat
test.bat
sub.bat
sub.bat
请按任意键继续. . .

实例:创建两个批处理文件,分别为 test.bat 和 sub.bat。在 test.bat 中调用 sub.bat,传递参数信息。

(1)test.bat 文件内容:

@echo off
echo test.bat
call sub.bat arg1 arg1
call C:\Users\Administrator\Desktop\sub.bat arg1 arg1
pause

(2)sub.bat 文件内容:

@echo off
echo sub.bat
echo 第一个参数:%1
echo 第二个参数:%2

输出结果:

C:\Users\Administrator\Desktop> test.bat
test.bat
sub.bat
第一个参数:arg1
第二个参数:arg1
sub.bat
第一个参数:arg1
第二个参数:arg1
请按任意键继续. . .

CALL 语句扩展

如果命令扩展被启用,CALL 会如下改变,CALL 命令可以调用指定标签后面的语句(即调用子程序)。语法是:

CALL :label [arguments]

参数说明:

  • :label  用于指定调用位置的标签,与goto语句中使用的标签类似;

  • arguments  对于以 :label 开头的批处理程序(或子程序),指定要传送给其新实例的命令行信息,包括命令行选项、文件名、批处理参数或者变量;

  • /?  在命令提示符显示帮助;

实例:在批处理脚本中创建 :sub 标签,然后使用 call :sub 调用该标签。

@echo off
echo test.bat
call :sub
goto end

:sub
echo sub label
goto :eof
:end

pause

输出结果:

C:\Users\Administrator\Desktop> test.bat
test.bat
sub label
请按任意键继续. . .

实例:在批处理脚本中创建 :sub 标签,然后使用 call :sub arg1 arg2 调用该标签, 并且指定参数。

@echo off
echo test.bat
call :sub arg1 arg2
goto end

:sub
echo sub label
echo 第一个参数:%1
echo 第二个参数:%2
goto :eof
:end

pause

输出结果:

C:\Users\Administrator\Desktop> test.bat
test.bat
sub label
第一个参数:arg1
第二个参数:arg2
请按任意键继续. . .

CALL 参数扩展

另外,批脚本文本参数(%0、%1、等等)已如下改变:

(1)批脚本里的 %* 指出所有的参数(如 %1 %2 %3 %4 %5 ...),实例:

test.bat 文件内容:

@echo off
echo test.bat
call sub.bat arg1 arg2
pause

sub.bat 文件内容:

@echo off
echo sub.bat
echo 参数:%*

输出结果:

C:\Users\Administrator\Desktop> test.bat
test.bat
sub.bat
参数:arg1 arg2
请按任意键继续. . .

(2)批处理参数(%n)已被增强。您可以使用以下语法:

  • %~1    删除引号("),扩展 %1

  • %~f1    将 %1 扩展到一个完全合格的路径名

  • %~d1    仅将 %1 扩展到一个驱动器号

  • %~p1    仅将 %1 扩展到一个路径

  • %~n1    仅将 %1 扩展到一个文件名

  • %~x1    仅将 %1 扩展到一个文件扩展名

  • %~s1    扩展的路径只含有短名

  • %~a1    将 %1 扩展到文件属性

  • %~t1    将 %1 扩展到文件的日期/时间

  • %~z1    将 %1 扩展到文件的大小

  • %~$PATH:1    查找列在 PATH 环境变量的目录,并将 %1 扩展到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此修改符会扩展到空字符串

可以将增强符组合起来,可取得多重结果:

  • %~dp1    只将 %1 扩展到驱动器号和路径

  • %~nx1    只将 %1 扩展到文件名和扩展名

  • %~dp$PATH:1    在列在 PATH 环境变量中的目录里查找 %1,并扩展到找到的第一个文件的驱动器号和路径。

  • %~ftza1    将 %1 扩展到类似 DIR 的输出行。

在上面的例子中,%1 和 PATH 可以被其他有效数值替换。%~ 语法被一个有效参数号码终止。%~ 修定符不能跟 %* 使用。

实例:生成一个临时文件 tmp.txt,先将目录 C:\windows 设置为当前目录,调用子程序进行参数扩展;然后再恢复当前目录,调用子程序;观察参数扩展结果。

@echo off
echo 产生一个临时文件 > tmp.txt

REM 下行先保存当前目录,再将 c:\windows 设为当前目录
pushd c:\windows
call :sub tmp.txt

REM 下行恢复前次的当前目录
popd
call :sub tmp.txt
pause

del tmp.txt
exit

:sub
echo 删除引号: %~1
echo 扩充到路径: %~f1
echo 扩充到一个驱动器号: %~d1
echo 扩充到一个路径: %~p1 
echo 扩充到一个文件名: %~n1
echo 扩充到一个文件扩展名: %~x1
echo 扩充的路径指含有短名: %~s1 
echo 扩充到文件属性: %~a1 
echo 扩充到文件的日期/时间: %~t1 
echo 扩充到文件的大小: %~z1 
echo 扩展到驱动器号和路径:%~dp1
echo 扩展到文件名和扩展名:%~nx1
echo 扩展到类似 DIR 的输出行:%~ftza1
echo.

goto :eof

输出结果:

C:\Users\Administrator\Desktop> test.bat
删除引号: tmp.txt
扩充到路径: c:\Windows\tmp.txt
扩充到一个驱动器号: c:
扩充到一个路径: \Windows\
扩充到一个文件名: tmp
扩充到一个文件扩展名: .txt
扩充的路径指含有短名: c:\Windows\tmp.txt
扩充到文件属性:
扩充到文件的日期/时间:
扩充到文件的大小:
扩展到驱动器号和路径:c:\Windows\
扩展到文件名和扩展名:tmp.txt
扩展到类似 DIR 的输出行:c:\Windows\tmp.txt

删除引号: tmp.txt
扩充到路径: C:\Users\Administrator\Desktop\tmp.txt
扩充到一个驱动器号: C:
扩充到一个路径: \Users\Administrator\Desktop\
扩充到一个文件名: tmp
扩充到一个文件扩展名: .txt
扩充的路径指含有短名: C:\Users\ADMINI~1\Desktop\tmp.txt
扩充到文件属性: --a------
扩充到文件的日期/时间: 2020/06/16 13:21
扩充到文件的大小: 19
扩展到驱动器号和路径:C:\Users\Administrator\Desktop\
扩展到文件名和扩展名:tmp.txt
扩展到类似 DIR 的输出行:--a------ 2020/06/16 13:21 19 C:\Users\Administrator\Desktop\tmp.txt

请按任意键继续. . .
说说我的看法
全部评论(

goto :eof 语句作用如下:

(1)在无call的情况下,会直接退出批处理,此时等同于exit
(2)在call的情况下,会中止call,继续执行其他命令

代码里有call,为什么没有终止call,按逻辑来看,加了goto:eof会终止call然后输出:楼主!楼主!

而他是直接死循环,很不理解,代码放下面了:


goto _start
:system
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit
cd /d "%~dp0"
goto :eof
:_start
call :system
echo 楼主!楼主!
pause
exit

回复:

主要是这行代码:

%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit

影响到 goto :eof 语句,具体原因不是很清楚,可以去找资料,找到后希望留言,学习学习!!

运行下面这段call代码会死循环,楼主帮我看看


goto _start
:system
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit
cd /d "%~dp0"
goto :eof
:_start
call :system
echo 楼主!楼主!
pause
exit

回复:

这是因为 :system 子程序中的 goto :eof 语句没有起到跳出循环的作用,goto :eof 语句作用如下:

(1)在无call的情况下,会直接退出批处理,此时等同于exit
(2)在call的情况下,会中止call,继续执行其他命令

注意:读者不要轻易运行该脚本,该脚本将重复 “关闭旧DOS窗口,打开新DOS窗口”。

关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号