Dos 命令进阶——批处理(下)
for命令讲解思路图
FOR命令的作用主要是用来处理文本内容。
可以打开cmd输入"for /?" 来看下它的帮助文档
这里罗列出for命令的四个参数 /F,/D,/R,/L . 当然这些参数也是可以不加的(参数不区分大小写)
第一部分:
下面我们跑几个例子, 先看没有加任何参数的.
示例1:
@echo off
for %%a in (c:windows*.log) do echo %%a
pause
for命令无参数的操作演示
首先请大家看几个固定的格式,%%a是个变量。
批处理变量的命名规则是从小写a -- 小写z,和大写A -- 大写Z
实例分析:
执行命令将 (c:windows*.log) 中的操作结果逐个赋(传送)给 %%a 然后 Do 将 %%a 输入给 echo指令, 就会打印出 c:windows 目录下所有扩展名为 .log 的文件
还有一点需要注意的:
%%a 这样的变量命名方式只在编写批处理脚本时需要给变量名前加两个%, 如果是在CMD独立执行for命令行, 则只需要一个%, 即 %a 即可.
%和%%的区别应用
好,现在我们来学习for命令的第一个参数 /d, 打开帮助就可以看见。
系统帮助文档有说“如果数据集(set)中包含通配符, 则指定与目录名匹配,而不与文件名匹配”。
说明这个参数是 对目录进行相关操作的,而不是操作文件。
就是说, 加了 /d 这个参数的for命令行, 只能对目录进行操作(这样说感觉好像容易理解一些).
/d参数的基本格式:
FOR /D %variable IN (set) DO command [command-parameters]
示例2:
@echo off
for /d %%a in (*) do echo %%a
pause
for /d 参数的应用(只能操作当前目录)
for /d 参数的应用, 只操作脚本当前路径下的目录
for /d 参数指定操作路径
for /d参数, 给指定的操作路径两端添加双引号
它就只显示批处理文件所在当前路径下所有的文件夹(专业点就叫目录, directory),而文件就不会显示。这也就是/d这个参数的作用了,再来看个例子,也是我们前面讲到过的知识
示例3:
@echo off
for /d %%a in (?indows) do echo %%a
pause
for /d 在默认路径下执行脚本
for /d 在任意路径执行脚本
?可以匹配任意一个字符,所以它会打印出 c: 下所有以任意字符开头跟有indows的目录,这一点相信难不住学过基础的条友.
/r参数的基本格式:
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
检查以 [drive:]path 为根(起始点)的目录树,指向每个目录中的FOR 语句。如果在 /R 后没有指定目录,则使用脚本当前所在目录。如果数据集(set)为一个单点(.)字符,则枚举该目录树。
这个r参数应该是递归(recursion)查寻当前目录树下的指定类型文件的意思
系统帮助文档看起来不是那么容易理解,还是直接来看例子吧, 这样实在些:
示例1:
显示当前目录和子目录下所有的扩展名为.txt的文件
@echo off
for /r %%a in (*.txt) do echo %%a
pause
默认路径下
示例2 :
在c:的根目录以及子目录中搜索所有的扩展名为.exe的文件
@echo off
for /r C:opencv %%a in (*.txt) do @echo %%a
pause
指定路径下的文件
想要的文件都找到了, 至于你想对找到的文件做些啥子事情, 请在 DO 后面进行操作.
/l参数的基本格式:
FOR /L %variable IN (start,step,end) DO command [command-parameters]
该数据集表示以增量形式从开始到结束的一个数字序列。
因此,(1,1,5) 将产生序列 1 2 3 4 5,即从1开始循环, 每一次加1,直到5结束循环.
(5,-1,1) 将产生序列 (5 4 3 2 1), 即从5开始循环, 每一次减1, 直到1结束循环.
可能有的条友还不是很明白。那还来看例子
示例1:
@echo off
for /l %%a in (1,1,5) do @echo %%a
pause
让 for /l 只作计数
执行后就显示了1 2 3 4 5,首先说下(1,1,5)对应的就是基本格式中的(start,step,end)也就是
开始数、递增量、终止数。那么这个do后面的命令大家可以修改啊,再来看个例子理解下
示例2:
@echo off
for /l %%a in (1,1,3) do echo 条友们万岁!
pausefor /l
也可以跑跑龙套
/f参数的基本格式:
FOR /F "ParsingKeywords" %%Variable IN (FileNameSet) DO command [command-parameters]
从帮助文档中我们知道,for命令主要是用它来解析文件。那么前面几个参数并没有关于用for来解析文件的功能.
重头戏就是这个/f参数了, 这个参数的功能是很强大的,大家要学好它哦
"ParsingKeywords" 代表的是下列这些选项参数:
eol=c - 指一个行注释字符的结尾(就一个)
skip=n - 指在文件开始时忽略的行数
delims=xxx - 指分隔符集。这个替换了空格和跳格键的默认分隔符集
tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n格式为一个范围。通过 nth 符号指定 mth。如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。
usebackq - 指定新语法已在下类情况中使用:在作为命令执行一个后引号的字符串并且一个单引号字符为文字字符串命令并允许在filenameset中使用双引号扩起文件名称。
上面那些帮助文档的内容也只有天才才能看懂了, 反正小编没看懂。
那就一起试着来吧, 顺便大家也看看热闹, 看看能不能理解每个参数的作用, 如果能理解, 小编的努力就算是没白费.
示例3:
@你们好吗
欢迎 欢迎 热烈欢迎
感谢 条友们的 关注支持 条友们万万岁!
感谢 条友们的 关注支持 条友们万万岁!
感谢 条友们的 关注支持 条友们万万岁!
看清楚了吗
;懂了吧
保存为以个文本文件为test.txt,用for /f来解析试试看
@echo off
for /f "[email protected] tokens=1 delims= " %%i in (test.txt) do @echo %%i
pause
for /f 解析文件内容 tokens=1
for /f 解析文件内容 tokens=4
说明:
关键字eol=后面的符号表示 忽略以该符号开头的行
关键字tokens=1是什么意思? 在此它表示每一行的第一块,那么如果tokens=2呢,当然是表示每一行的第二块…那么每行块划分的依据就是关键字 "delims=" 它了, 这里是以空格来划分的,大家可以灵活使用.
如果是别的特殊符号,比如“;”那么就可以写成“delims=;”, 想来大家应该有些小明白了吧。
在来看示例4:
@echo off
for /f "delims=" %%i in (test.txt) do @echo %%i
pause
默认解析参数的演示
这会没加eol=这个参数
注意: for /f 默认情况下就是eol=; 所以它会显示这些内容,
之所以加这个"delims="是因为for /f默认情况分隔符就是空格
所有参数都默认
综合理解一下上面几个参数。
示例5:
@echo off
for /f "eol=; tokens=1,2,3 delims= " %%a in (test.txt) do @echo %%a %%b %%c
pause
综合命令参数解析实例
和上面差不多,只是多显示了几块内容。注意%%a %%b %%c要按26个英文字母的顺序来写,这点希望大家记住。
再来看个例子
示例6:
@echo off
for /f "skip=5 tokens=*" %%i in (test.txt) do @echo %%i
pause
for /f skip参数的使用
这个skip=5表示的是跳过前面5行数,用数字来表示,tokens=*表示显示所有的信息
第二部分:
另外,FOR 变量参照的替换已被增强。您现在可以使用下列选项语法:
~I - 删除任何引号("),扩展 %I
%~fI - 将 %I 扩展到一个完全合格的路径名
%~dI - 仅将 %I 扩展到一个驱动器号
%~pI - 仅将 %I 扩展到一个路径
%~nI - 仅将 %I 扩展到一个文件名
%~xI - 仅将 %I 扩展到一个文件扩展名
%~sI - 扩展的路径只含有短名
%~aI - 将 %I 扩展到文件的文件属性
%~tI - 将 %I 扩展到文件的日期/时间
%~zI - 将 %I 扩展到文件的大小
%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串
注意: 在CMD命令提示符中执行的话需要输入一个%号,这也是很多人容易犯的错误,这里我举几个几个例子来让大家理解它们的意思:
看看这个 ~I - 删除任何引号("),扩展 %I
将下列内容保存为一个名为test.txt的文本文件
"条友们万万岁!"
"条友们万万岁!"
"条友们万万岁!"
"条友们万万岁!"
示例1:
@echo off
for /f "delims=" %%i in (test.txt) do @echo %%~i
pause
for /f 不给扩展变量加~时
for /f 加了~的扩展变量的效果
可用作扩展变量的不一定非要是 I, 其它字符也可以的
大家可以看见,其实这个参数就是用来去掉两端引号的,但是去"号它也是有一定规律的。假如在词语中间的"它是不会去掉。这一点希望大家注意一下。
理解了这个~i,我们再来看个%~fI 的例子
示例2:
@echo off
for /f "delims==" %%i in ('dir /b') do @echo %%~fi
pause
先看一下 dir 与 dir /b 这个带不带 /b 参数的区别
默认dir不带任何参数
dir /b 参数的作用
这是在没有使用 %~fi 这前
使用 %~fi 命令扩展后的效果
%~fI其实就是将 %I 扩展到一个完全合格的路径名(每个文件的绝对路径),大家可以对比一下有什么不一样的地方就明白了
"delims==" 这个参数的写法, 两个=号与一个=号的效果是一样的, 不用纠结.
再来看下一个例子:
示例3:
@echo off
for /f "delims==" %%i in ('dir /b') do @echo %%~di
pause
for /f 中 %~di变量扩展的效果
为什么只显示了批处理所在路径的驱动器号呢,这就是%~di的关系了,它就是用来显示批处理所在路径驱动器号的,明白了吗?
%~pI - 仅将 %I 扩展到一个路径
示例4:
@echo off
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~pi
pause
for /f %~pi 变量扩展的效果
也就是只显示路径而不显示文件名,那么下面的都可从命令行帮助中就可理解了
%~sI - 扩展的路径只含有短名
在来看示例5:
@echo off
for /f "delims=" %%i in ('dir/b') do @echo %%~si
pause
for /f %~si 扩展变量的演示
从字面上也可以理解了,在系统存在有长路径名和短路径名,我们来看下。就比如我们要切换目录吧,我在C:下要切换到C:Program Files目录下我就可以输入cd "Program Files" 注意双引号哦, 因为目录名中间有空格.
那么这就是一种长路径名的表示形式。那我们现在用短路径名来表示它,cd PROGRA~1(字母是大写的)是不是也切换进来了.那么我们怎么可以看见每个目录的短路径呢,可以通过输入 dir /x 就可以看见了。
%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串
来看个例子就知道是什么意思了
示例6:
FOR /F "delims==" %%i IN ("notepad.exe") DO @echo %%~$PATH:i
pause
先看下图中, 要知道PATH这个环境的值, 其值都是以分号隔开各文件夹的绝对路径
在%PATH%路径种搜索指定的文件,因为他是一个系统变量%PATH%,通过echo看下就知道它代表的是什么意思了
查看系统环境变量的结果
最后来看下它们的组合用法
%~dpI - 仅将 %I 扩充到一个驱动器号和路径
示例7:
@echo off
for /f "delims=" %%i in ('dir/b') do @echo %%~dpi
pause
请对比 %~di, %~pi, %~dpi这三个实例来理解
前面已经说到了,只是将他们组合在一起实用而已。
%%~dI 仅将 %I 扩展到一个驱动器号,%~pI- 仅将 %I 扩展到一个路径
%~nxI - 仅将 %I 扩充到一个文件名和扩展名.
for /f 下 %~ni扩展变量的应用
for /f 下 %~xi扩展变量的应用
for /f 下 %~xni扩展变量的应用
%~fsI - 仅将 %I 扩充到一个带有短名的完整路径名, 跟%~si的结果相同
%~dp$PATH:i - 查找列在路径环境变量的目录,并将 %I 扩充到找到的第一个驱动器号和路径。
%~dp$PATH:i 扩展变量的用法
%~ftzaI - 将 %I 扩充到类似输出线路的 DIR
这个也很简单,举例说明
最后在来看个例子
示例8:
@echo off
for /f "delims=" %%i in ("notepad.exe") do @echo %%~dp$PATH:i
pause
%~$PATH:I 是用来搜索文件的,前面有提到。
那么%%~dp$PATH:i是什么意思呢。就是如果搜索到notepad.exe这个文件,那么只显示它所在的%~dI驱动器号和%~pI扩展到一个路径,而文件名是不会显示的。如果要显示文件名那就得在加一个参数了,就是%~nI- 仅将 %I 扩展到一个文件名
延迟的环境变量扩展
要理解什么是“延迟的环境变量扩展”,首先要理解什么是“环境变量扩展”。
(搬砖源: https://www.cnblogs.com/minisculestep/p/4959612.html)
cmd在解释我们的命令的时候,首先会读取命令行一条完整的命令,然后对其进行一些命令格式的匹配操作,看你所输的命令格式是否正确。如果我们要在命令中引用一些变量,那么我们需要在变量的两边各加一个%号,使cmd在解释我们的命令的时候能够识别这个变量,例如%name%。当cmd读取我们的命令进行格式匹配的时候,就会发现name这个字符串两边各加了一个%,就不会把它当作普通字符串处理,而是把它当作一个变量处理,变量名就叫做name。然后cmd就会查找这个变量的值,用该值替换掉%name%,最后执行这个替换好的命令。这个替换的过程就叫做环境变量扩展。
什么是延迟的环境变量扩展,我们都知道命令行解释器在解析执行批处理文件时是将一条完整的命令来解析执行的。(对于if、for这样的命令,可以将命令嵌套在括号里,所以一个完整的if命令可能包含多个需要执行的命令,但是cmd在解释这类命令的时候,会把它当作一条完整的命令,从而导致出现一些问题。),这个应该不难理解吧。
示例代码 :
@echo off
set /a var = 0
for /l %%m in (1,1,5) do (
set /a var = %%m
echo %var%
)
pause
执行结果:
延迟环境变量示例
这是因为在命令执行之前,变量便进行了替换,导致嵌套在for命令里的操作没有体现出来。这时候,“延迟的环境变量扩展”的概念被提出来了。“延迟的环境变量扩展”,即每条命令在执行之前,才将变量进行替换,以保证对变量的任何修改都可以实时生效。
我们可以使用“setlocal enabledelayedexpansion”命令来开启延迟的环境变量扩展,启用后,我们使用 !name! 来进行取值,而不是%name%。
修改后的代码如下:
@echo off
setlocal enabledelayedexpansion
set /a var = 0
for /l %%m in (1,1,5) do (
set /a var = %%m
echo !var!
)
pause
执行结果:
开启延迟变量扩展功能后