探索Windows命令行系列(3):命令行脚本基础
命令行脚本是包含可执行命令的文本文件,这些命令一般和命令行窗口键入的命令一致。脚本文件中的命令就是标准的文本字符,因此可以通过普通的文本编辑器,如 Windows 记事本来编辑。在脚本中输入命令时,需要注意的是,每一条命令,或者每一组需要一起执行的命令,都因该保存在脚本的单独一行中,以便确保命令的正确执行。
在常见的编程语言中,如 C/C++/C# 等语言中每条语句都要用分号来表示结束。而在命令行脚本中,没有诸如分号之类的特定终止符,而是通过断行(比如按下Shift+Enter键)、回车与断行(按下Enter键)、文件结尾标志三种方式来表示语句结束。
1、实用功能
1.1、为脚本添加注释
rem 命令用于注释单行命令,类似与 C# 等语言中注释符//
。需要注意的是,当在批处理文件中通过 rem 命令注释了某一行之后,该行就不会被执行了,但默认被注释的命令内容还是会被回显到窗口上,这时候可以结合下面将要讲到的 @ 命令,写成 @rem 就一定不会显示了。
1.2、控制命令的回显
用echo
和@
两个命令,echo
命令用于在命令回显消息、关闭或打开命令回显(当回显处于打开状态,执行批处理文件时将逐条显示批处理文件中的命令行;相反,当回显处于关闭状态时,不会显示命令行本身),而@
命令用于以行为单位控制命令的回显方式。
示例 1:向命令行回显一条消息(Hello Word!)
echo Hello Word!
示例 2:关闭命令行回显(关闭回显之后就看不到命令提示符前的路径了)
echo off
示例 3:打开命令行回显(默认打开)
echo on
示例 4:在任何一行命令前加上@
即可关闭该行的回显
@echo Hello Word!
1.3、使用数学表达式
命令行脚本支持算术运算、赋值运算、比较运算、按位运算等常见的数学运算。所有数学运算都得在set
命令的参数/a
之后进行。
示例:
set /a add=3+7
set /a sub=3-7
set /a mul=3*7
set /a div=5/2
set /a mod=5%2
set /a exp=2*2*2
1.4、向脚本传递参数
在调用命令行脚本的时候还可以向脚本传递参数。传递给脚本的每一个参数都可以用形参进行检查和解释。第1个参数用%1
表示,第2个参数用%2
表示,依次类推,第9个形参为%9
。但如果向脚本传递的参数多于9个,则会被保存到一个特殊的参数变量%*
中去,通过shift
命令可以查看%*
中的实参;另外在必要的时候,还可以通过shift
命令进行形参移位,譬如shift /2
表示忽略第2个参数,从第3个参数开始往前移动。还有一个特殊的形参是%0
,它代表当前脚本的名称。
示例:
在 D 盘新建一个记事本,然后键入下面的脚本:
@echo 当前脚本的名称是:%0
@echo 第1个参数的值是:%1
@echo 第2个参数的值是:%2
@pause
将记事本改名为 try.bat,然后打开命令行(cmd.exe)调用该脚本:
try abc 123
结果如下:
2、使用变量
在命令行脚本中,我们通常所说的变量更可能是指环境变量。环境变量有多种来源,有内置在操作系统之中的,也有在系统启动时来自系统硬件的,这些被称之为内置系统变量,对所有 Windows 进程都可用。系统变量也可来自 Windows 注册表。除内置系统变量之外,还有一些登录时设置的变量,这种变量被称为内置用户变量。
通过set
命令可以查看当前命令行实例中所有变量及变量值。除标准的系统变量和用户变量之外,还可以通过set
命令在命令行中随时创建或设置变量。
有些变量在命令行中有着特殊的含义,如 path、computername、homedrive、errorlevel 等。其中 errorlevel 变量可以追踪最近使用命令的退出代码。如果命令正常执行,则错误级别为 0;如果命令在执行过程中出错,则错误级别会被设置为一个适当的非 0 值(1 表示一般的错误,2 表示执行错误,意味着命令没有正确执行,-2 表示算数错误)。
2.1、变量的命名及定义
在命令行脚本中,变量名是大小写不敏感的,在定义变量的时候可以区分大小写,但在调用的时候不区分大小写。变量名可以是任意字母、数字或字符的组合,如 2s、38、? 等理论上都是合法的变量名。尽管如此,我们也还是应该要使用便于理解的名字来做为变量名。
在命令行中声明变量时必须同时为其赋值,定义变量的语法如下:
set variable_name=variable_value
在变量名和变量值中,空格都是有效的,但一般不建议使用。命令行也不对具体的数据类型进行区分,所有的变量都是以字符的形式存储,即使变量值设置为数值也是如此。但在进行数学运算的时候,命令行是可以判断出字符串是否为数值的。
有些字符是命令行的保留字符,如 @、<、>、&、|、^ 等,在使用这些字符的时候,无论出现在变量值中的那个位置,都必须使用转码字符 ^ 对其进行转码。
示例:
set var1=abc
set var2=985
set var3=3.14
set var4="ok"
set var5="2^&3"
set "name=张三"
2.2、调用变量
在命令行中任何需要用到变量的地方都可以调用变量,调用的方式是用两个百分号包裹变量名,即%variable_name%
。
示例:
echo %var3% 输出变量 var3 的值
echo %name% 输出变量 name 的值
cd %systemroot%\system32 切换到系统目录下的 system32 目录中
set syspath=%systemroot%\system32 定义一个变量 syspath 并用其它变量为其赋值
综合案例:
@rem 定义变量接收用户输入
@echo off
@set /p str=请输入任意内容,然后回车:
@echo 您刚刚输入的内容是:%str%
@pause
2.3、变量的作用域
在命令行中用set
命令所做修改的作用范围是局部化的,也就是说set
命令的作用仅限当前会话窗口,窗口关闭后之前的修改就会失效。
有时候可能还需要对变量的作用范围做进一步约束,使其仅作用于脚本的某一部分。要做到这一点,可以通过setlocal
命令来标记一个局部范围的开始,使用endlocal
命令来标记一个局部范围的结束。
示例:
setlocal
set cnt=5
endlocal
在一个比较长的作用范围内,使用完变量之后,应该要对其进行适当处理,以便释放该变量占用的内存,防止无意间再次引用该变量时出现预期之外的结果。在命令行中只要把变量的值设置为空,该变量就不复存在了。
示例:
set var3=
3、结构语句
3.1、选择语句
命令行中的选择语句是 if,该语句有 3 中不同的形式,本节将逐一介绍。
普通的 if 语句:如果条件为真则执行该语句,否则绕过该语句。
语法(语法中的圆括号并非必须,但使用圆括号会使语句结构更加清晰):
if condition (statement1) [else (statement2)]
示例:
set v1=1
if %v1%==1 (echo is one) else (echo is not one)
if %v1%==1 (hostname & ver & ipconfig /all)
如果存在 try.bat 文件,则把该文件的内容输出到控制台:
if exist try.bat type try.bat
if not 语句:如果条件为假则执行该语句,否则绕过该语句。
语法:
if not condition (statement1) [else (statement2)]
示例:
if not %errorlevel%==0 (echo error has occurred) else (echo running well)
if defined & if not defined:这两个语句用于检查某变量是否存在。
语法:
if defined variable_name statement
if not defined variable_name statement
在用于安全检查的时候,这两个语句非常有用。第一个语句是在变量存在的时候,执行某条命令。第二个语句是在变量不存在的时候,执行某条命令。
示例:
if defined v1 (echo %v1%)
3.2、迭代语句
命令行中的迭代语句是 for,该语句与常见的编程语言(如 C#)中的 for 循环有很大的不同。命令行中的 for 语句主要用于在成组的文件与目录中进行迭代处理,并以行为基础分析文本文件、字符串以及命令的输出信息。
最常见的 for 语句语法如下:
for iterator do (statement)
语法中的 iterator 用于控制 for 循环的执行。对 iterator 中每一个步骤或元素,都会执行特定的语句。它可以是单一的一条命令,也可以是使用命令管道、命令链、命令分组等技术组合起来的多条命令。
iterator 通常包含一个初始化变量和一组需要反复执行的元素,比如需要遍历的一组文件或某范围内的一组值。初始化变量也就是要使用的值的占位符,使用初始化变量时,需要注意以下几点:
- 变量只存在于 for 语句的上下文中。
- 变量名必须在 a~z 或 A~Z 的范围内,比如 %%a、%%b、%%c。
- 变量名是大小写敏感的,也就是说,%%a 与 %%A 是不同的。
常见迭代形式表如下:
迭代功能 | 语法格式 |
---|---|
文件集合 | for %%variable in (fileSet) do statement |
目录集合 | for /D %%variable in (directorySet) do statement |
子目录中的文件 | for /R[path] %%variable in (fileSet) do statement |
遍历一系列的值 | for /L %%variable in (stepRange) do statement |
分析文本文件、字符串以及命令输出 | for /F[options] %%variable in (source) do statement |
上表中提供的迭代形式也可以在命令行中交互式地使用 for 语句,这种情况下,应该使用 %variable,而不是 %%variable。除此之外,脚本中的 for 语句与在命令行中使用 for 语句是完全一样的。
遍历一系列值:用于操作数值。
语法:
for /l %%variable in (start,step,end) do (statement)
示例(输出 1~9 之间的奇数):
@for /l %%v in (1,2,9) do @echo %%v
在成组的文件中迭代执行:用于操作文件组中的文件。
语法:
for %%variable in (fileSet) do statement
语法中的 fileSet 用于指定需要处理的文件集,文件集可以是如下形式。
- 通过文件名指定为单独的文件,如 myfile.txt。
- 通过文件名通配符指定一组文件,如 *.txt。
- 使用空格分割的多个文件或文件组,如 myfile.txt *.doc *.docx。
示例 1(输出 D:\Workspace 目录中所有 txt 文件的全路径名):
for %%i in (D:\Workspace\*.txt) do (echo %%i)
示例 2(输出 D:\Workspace 目录及其子目录中所有 txt 文件的全路径名):
for /r D:\Workspace %%i in (*.txt) do (echo %%i)
示例 3(输出 D:\Workspace 目录及其子目录中所有 jpg 或 png 文件的全路径名):
for /r D:\Workspace %%i in (*jpg,*png) do (echo %%i)
示例 4(输出 D:\Workspace 目录及其子目录中所有文件的全路径名):
for /r D:\Workspace %%i in (*) do (echo %%i)
示例 5(输出 D:\Workspace 目录及其子目录中所有名称包含 windows 的文件全路径名):
for /r D:\Workspace %%i in (*windows*) do (echo %%i)
示例 6(输出 D:\Workspace 目录及其子目录中所有路径包含 windows 的文件夹全路径+windows):
for /r D:\Workspace %%i in (windows) do (echo %%i)
从上述几个例子中也能看出来,匹配模式中第一个字符必须是星号,否则就匹配不到文件了。如果完全不带星号则会匹配到路径包含指定字符的文件夹全路径+指定字符。
在目录中迭代执行:用于操作目录组中的目录。
示例(输出 D:\Workspace\ 中所有的子目录名):
for /d %%v in (D:\Workspace\*) do echo %%v
3.3、子程序 & 过程
使用子程序:也就是通过goto
跳转到另一段程序继续执行。goto
的作用是将命令解释器直接跳转到批处理脚本中某个标记行。
示例:
@if not defined v (@echo error: Undefined parameters!) & (goto exit)
@if %v%==1 goto subroutine1
@if %v%==2 goto subroutine2
@if %v%==3 goto subroutine3
@goto exit
:subroutine1
@echo In subroutine 1
@goto exit
:subroutine2
@echo In subroutine 2
@goto exit
:subroutine3
@echo In subroutine 3
@goto exit
:exit
@echo Exiting...
使用过程:也就是在脚本中调用其它脚本,而又不会退出原脚本。进行过程调用时,命令行会执行调用的脚本,逐一执行其中的命令,结束后返回到原脚本,并从过程调用语句的下一行语句开始执行。
示例:
@if %v%==1 call file1
上例中,如果不适用call
语句,也能调用 file1 脚本,但在 file1 脚本执行完毕之后控制权不会返回给调用者(原脚本)。
call 命令用于调用另外一个批处理文件。常用的方式就是call sample.bat
,新扩展的一个用法是call :label arguments
,也就是用 call 来调用 bat 文件内部的一段脚本,然后用 exit 来退出当前的 call 调用。
4、总结
本文主要讲述了命令行脚本的注释、回显、参数、变量、结构控制语句等基础内容。
本文链接:http://www.cnblogs.com/hanzongze/p/cmd-script-base.html
版权声明:本文为博客园博主 韩宗泽 原创,作者保留署名权!欢迎通过转载、演绎或其它传播方式来使用本文,但必须在明显位置给出作者署名和本文链接!个人博客,能力有限,若有不当之处,敬请批评指正,谢谢!
探索Windows命令行系列(3):命令行脚本基础的更多相关文章
- 探索Windows命令行系列(5):几个实用的命令例解
1.关机命令(shutdown) 2.管理 Windows 服务(sc) 3.管理任务进程(tasklist.taskkill) 4.显示 TCP/IP 配置值(ipconfig) 5.网络诊断工具( ...
- 探索Windows命令行系列(1):导航目录
探索Windows命令行系列(1):导航目录 探索Windows命令行系列(2):命令行工具入门 探索Windows命令行系列(3):命令行脚本基础 探索Windows命令行系列(4):通过命令操作文 ...
- 探索Windows命令行系列(2):命令行工具入门
1.理论基础 1.1.命令行的前世今生 1.2.命令执行规则 1.3.使用命令历史 2.使用入门 2.1.启动和关闭命令行 2.2.执行简单的命令 2.3.命令行执行程序使用技巧 3.总结 1.理论基 ...
- yii2 命令行执行php命令 commands(命令)
YII2可以在命令行执行php命令,作为半路出家的撩妹君可谓是抠脚福音.作为一个屌丝级的程序员必须要有智能提示代码的IDE,比如PHPstorm.至于如何免费使用嘛..... 首先明白YII2自带的c ...
- liunx 命令行快捷键 常用命令
常用指令 ls 显示文件或目录 -l 列出文件详细信息l(list) -a 列出当前目录下所有文件及目录,包括隐藏的a(all) mkdir ...
- 探索Windows命令行系列(7):通过命令编译C#类和Java类
1.编译 C# 类 1.1.C# 编译工具 1.2.编译一个 C# 类 1.3.编译多个 C# 类 2.编译 Java 类 2.1.Java 编译工具 2.2.编译 Java 类 3.组合命令符 4. ...
- 探索Windows命令行系列(4):通过命令管理文件和文件夹
1.文件夹操作 1.1.DIR(directory)命令 1.2.TREE 命令 1.3.CD(change directory)命令 1.4.MD(make directory)命令 1.5.RD( ...
- 探索Windows命令行系列(6):活用批处理解决实际问题
1.批量修改文件名 2.批量重启服务 3.全盘搜索指定文件 3.1.全盘搜索名称为 mm.jpg 的文件,获取其全路径 3.2.查找系统中所有名称以 .docx 结尾的文件 4.调用可执行程序 4.1 ...
- 探索Windows命令行系列(4):通过命令操作文件和文件夹
1.文件夹操作 1.1.DIR(directory)命令 1.2.TREE 命令 1.3.CD(change directory)命令 1.4.MD(make directory)命令 1.5.RD( ...
随机推荐
- 利用Python进行简单的图像识别(验证码)
这是一个最简单的图像识别,将图片加载后直接利用Python的一个识别引擎进行识别 将图片中的数字通过 pytesseract.image_to_string(image)识别后将结果存入到本地的txt ...
- 计算facebook sdk需要的key hashes
1. 下载openssl,在C盘创建openssl文件夹,解压下载的zip到openssl文件夹. 2. 找到debug.keystore. windows下在C:\Users\用户名\.androi ...
- textView布局的一点体会
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制
ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...
- 前端设计技巧——用 Promise 处理交互和异步
本文仅表达前端的一些设计技巧,如果您在查阅js技术,请忽略此文! 前端开发经常会遇到这样的场景: 当满足一定条件时,需要弹出一个模态框,以便接收用户的输入.然后根据不同的输入,进行不用的操作. (ps ...
- WebSocket+MSE——HTML5 直播技术解析
作者 | 刘博(又拍云多媒体开发工程师) 当前为了满足比较火热的移动 Web 端直播需求,一系列的 HTML5 直播技术迅速的发展起来. 常见的可用于 HTML5 的直播技术有 HLS.WebSock ...
- Java IO流之转换流
一.转换流 1.在IO包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流-字符流的转换流 2.转换流用于在字节流和字符流之间转换 3.转换流本身是字符流 二.两种转换流 Ou ...
- javaSE_06Java中的数组(array)
1.什么是数组? 顾名思义,即为数据的组合或集合,数组就是用来表示一组数据的. 比如没有数组之前,我们要存储多个姓名的信息 String name1; String name2; String nam ...
- DOM知识梳理
DOM 我们知道,JavaScript是由ECMAScript + DOM + BOM组成的.ECMAScript是JS中的一些语法,而BOM主要是浏览器对象(window)对象的一些相关知识的集合. ...
- css中那些容易被我们程序猿所忽略的选择器
css中那些容易被我们程序猿所忽略的选择器 作为一个程序猿,我们可能会遇到这样的问题,假如:有5个li,要求给第三个li设置背景颜色怎么办?有人会说,用JS啊,循环遍历出第三个不就行了.但是,用JS解 ...