批处理命令 - for

0、功能

Runs a specified command for each file in a set of files.
对一组文件中的每一个文件执行某个特定命令。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1、FOR命令简介

for命令的基本用法如下,主要是处理文件\文件夹\命令结果.

FOR %variable IN (set) DO command [command-parameters]

  %variable          # Specifies a single letter replaceable parameter. ;指定一个单一字母可替换的参数,简单的说就是vaiable取值范围只能是a~z和A~Z中的一个字母。
FOR 变量是单一字母、分大小写 是全局的变量,所以不能同时使用超过 52 个
  (set)              # Specifies a set of one or more files.  Wildcards may be used. ;指定一个或一组文件。可以使用通配符。
command # Specifies the command to carry out for each file. ;指定对每个文件执行的命令。
command-parameters # Specifies parameters or switches for the specified command. ;为特定命令指定参数或命令行开关。 To use the FOR command in a batch program, specify %%variable instead of %variable. Variable names are case sensitive, so %i is different from %I.
在批处理程序中使用 FOR 命令时,指定变量请使用 %%variable 而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I.
例如 echo %%T echo 是 command, %%T 则是 echo 的 command-parameters

1.1、应用举例1 - 删除当前文件文件夹下的1.txt、2.txt、3.txt、4.txt

@echo off
for %%i in (1,2,3,4) do del %%i.txt
pause

1.2、应用举例2 - 删除当前文件文件夹下所有txt文件

@echo off
for %%i in (*.txt) do del %%i
pause

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2、FOR命令的参数

FOR有4个参数 /d   /l   /r   /f   他们的大体用途如下

 /d    # Directory ;操作目录
/r # Recursion ;递归目录,操作所有目录下的文件
/f # File ;操作文件和字符串
/l # Iteration ;迭代器,产生有序序列

2.1、参数/D - 操作目录

FOR /D %variable IN (set) DO command [command-parameters]
If set contains wildcards, then specifies to match against directory names instead of file names.
如果集中包含通配符,则指定与目录名匹配,而不与文件名匹配,只能显示当前目录下的目录名字

2.1.1 应用举例1 - 打印C盘根目录下的所有文件夹的名称(只有根目录的文件夹,没有子文件夹)

@echo off
cd c:
for /d %%T in (*) Do echo %%T
pause

2.1.2 应用举例2 - 打印C盘根目录下以"P"开头的文件夹

@echo off
cd c:
for /d %%T in (P*) Do echo %%T
pause

Note: P不区分大小写

2.1.3 应用举例3 - 打印C盘根目录下,文件夹名称是1~3个字符的文件夹

@echo off
cd c:
for /d %%T in (???) Do echo %%T
pause

Note: 汉字算2个字符

2.1.4 应用举例4 - 打印C盘根目录下,文件夹名称是以P或W开头的文件夹

@echo off
cd c:
for /d %%T in (P*, W*) Do echo %%T
pause

Note: P 和 W 不区分大小写

2.1.5 应用举例5 - 打印C盘根目录下,文件夹名称是以P或者文件夹名称是1~3个字符的文件夹

@echo off
cd c:
for /d %%T in (P*, ???) Do echo %%T
pause

Note: 多种筛选条件随你组合,只要用","逗号分隔开就行

2.2、参数/R - 操作目录下的文件

FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

Walks the directory tree rooted at [drive:]path, executing the FOR statement in each directory of the tree.  
If no directory specification is specified after /R then the current directory is assumed.
If set is just a single period (.) character then it will just enumerate the directory tree.
检查以 [drive:]path 为根的目录树,指向每个目录中的 FOR 语句。
如果在 /R 后没有指定目录规范,则使用当前目录。
如果集仅为一个单点(.)字符,则枚举该目录树,即只操作文件夹,不操作文件。

2.2.1、应用举例1 - 打印出C盘目录下所有的exe文件名

@echo off
for /r c:\ %%T in (*.exe) do echo %%T
pause

因为/R 参数的作用是递归目录,所以无论多深路径下的exe都会被找到

2.2.2、应用举例2 - 打印出当前目录(脚本所在目录)下所有的exe文件名

@echo off
for /r %%T in (*.exe) do echo %%T
pause

2.2.3、应用举例3 - 打印出C盘根目录下所有的文件夹及其子文件夹的名字(总之是个文件夹就打印其名字,不管他的路径有多深)

@echo off
for /r c:\ %%T in (.) Do echo %%T
pause

这个是特例,只枚举目录树,而不枚举文件名

2.3、参数/L - 生成序列

FOR /L %variable IN (start,step,end) DO command [command-parameters]

The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would generate the sequence (5 4 3 2 1)
该集表示以增量形式从开始到结束的一个数字序列。
因此,(1,1,5)将产生序列1 2 3 4 5,(5,-1,1)将产生序列(5 4 3 2 1)
总结来说,就是等差数列.

2.3.1、应用举例1 - 打印出1 ~ 5

@echo off
for /l %%i in (1,1,5) do echo %%i
pause

Note : 只能按行打印, 不能将1~5输出到1行中

2.3.2、应用举例2 - 打开5个计算器程序

@echo off
for /l %%i in (1,1,5) do start calc
pause

2.4、参数/F - 操作文件与命令的输出结果

这个可能是最常用的,也是最强的命令,主要用来处理文件和一些命令的输出结果。

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]

or, if usebackq option present:

如果使用了usebackq 选项, 处理方式如下


FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
  FOR /F ["options"] %variable IN ('string') DO command [command-parameters]
  FOR /F ["options"] %variable IN (`command`) DO command [command-parameters]

file-set is one or more file names.  Each file is opened, read and processed before going on to the next file in file-set.
Processing consists of reading in the file, breaking it up into individual lines of text and then parsing each line into zero or more tokens.
The body of the for loop is then called with the variable value(s) set to the found token string(s).
By default, /F passes the first blank separated token from each line of each file.
Blank lines are skipped. You can override the default parsing behavior by specifying the optional "options" parameter.
This is a quoted string which contains one or more keywords to specify different parsing options. The keywords are:
file-set 为一个或多个文件名。继续到 file-set 中的下一个文件之前,每份文件都被打开、读取并经过处理。处理包括读取文件,将其分成一行行的文字,
然后将每行解析成零或更多的符号。然后用已找到的符号字符串变量值调用 For 循环。
默认方式,/F 通过每个文件的每一行中分开的第一个空白符号。跳过空白行。您可通过指定可选 "options" 参数替代默认解析操作。
这个带引号的字符串包括一个或多个指定不同解析选项的关键字。这些关键字为:
eol=c # specifies an end of line comment character(just one) ;指一个行注释字符的结尾(就一个)
skip=n # specifies the number of lines to skip at the beginning of the file.指在文件开始时忽略的行数。
delims=xxx # specifies a delimiter set. This replaces the default delimiter set of space and tab. 指定分隔符集。这个替换了空格和跳格键的默认分隔符集。
tokens=x,y,m-n # specifies which tokens from each line are to be passed to the for body for each iteration.
This will cause additional variable names to be allocated. The m-n form is a range,specifying the mth through the nth tokens.
If the last character in the tokens= string is an asterisk,
then an additional variable is allocated and receives the remaining text on the line after the last token parsed.
指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n格式为一个范围。通过 nth 符号指定 mth。
如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本 usebackq # specifies that the new semantics are in force,where a back quoted string is executed as a command and
a single quoted string is a literal string command and allows the use of double quotes to quote file names in filenameset.
指定新语法已在下类情况中使用:在作为命令执行一个后引号的字符串并且一个单引号字符为文字字符串命令并允许在 file-set中使用双引号扩起文件名称。
微软给出的解释似乎狗屁不通,这个选项的具体用法见下面的例子.

处理文件时, 将文件的每一行作为一个元素, for 循环 每次处理的就是 一行文本. for命令会跳过空白行.

2.4.1、不使用usebackq 选项

#不使用 usebackq 选项
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] # 处理文件, 文件在file-set文件集合中,注意,文件名和路径中都不可以有空格,不能用双引号括起来,否则需要使用usebackq选项
FOR /F ["options"] %variable IN ("string") DO command [command-parameters] # 处理字符串, 要处理的字符串就是双引号括起来的内容
FOR /F ["options"] %variable IN ('command') DO command [command-parameters] # 处理命令的结果, 在DO 后面的command执行之前先执行括号中用单引号括起来的命令,该命名的输出结果作为for的输入

2.4.1.1、处理文件

FOR /F 命令主要是 处理一些有固定格式的文件

2.4.1.1.1、应用举例1 - 显示文件内容

假设C盘根目录下有一个文件名字叫"myfile1.txt", 其中文件内容如下

The_First_Line
The_Second_Line
The_Thrid_Line
The_Fourth_Line

想要显示完整的文件内容可以使用 type myfile1.txt 命令, 但是for命令也可以实现,可以使用下面的批处理脚本程序

@echo off
for /f %%T in (C:\myfile1.txt) do echo %%T
pause

使用上面的脚本显示文本内容与type命令相比会有如下限制

①会忽略空行, 空行不会输出

②一行文本中不能有空格或者跳格键(TAB),否则只能输出空格或者跳格键之前的文本

下面来看一个具体的例子

假设C盘根目录下有一个文件名字叫"myfile2.txt", 其中文件内容如下

第1行第1列 第1行第2列 第1行第3列 
第2行第1列 第2行第2列 第2行第3列
第3行第1列 第3行第2列 第3行第3列

使用上面的脚本后,输出结果如下: (空行被忽略了, 每行只打印空格之前的字符)

第1行第1列
第2行第1列
第3行第1列

★为什么会忽略空行呢?

→for /f 命令的默认属性, 不可更改, 就是规定

★为什么会每行只打印空格或者跳格键之前的字符?

→这是因为"delims" 选项的默认值是空格 和 跳格键

所以上面的脚本等价于下面的脚本(注意等号后面是一个空格+一个TAB)

@echo off
for /f "delims= " %%T in (C:\myfile2.txt) do echo %%T
pause

假设C盘根目录下有一个文件名字叫"myfile3.txt", 其中文件内容如下

第1行第1列,第1行第2列,第1行第3列
第2行第1列,第2行第2列,第2行第3列
第3行第1列,第3行第2列,第3行第3列

如果只想要筛选出第1列的文本, 使用下面的脚本可以完成

@echo off
for /f "delims=," %%T in (C:\myfile3.txt) do echo %%T
pause

delims 选项用来指定分隔符,使用该选项后,默认的分隔符(空格和TAB)就无效了,

分隔符可以有多种,依次在delims=后面罗列出来即可,多个分隔符之间不可以有其他符号,是紧密的连在一起的.

如果只想要筛选出第2列的文本, 使用下面的脚本可以完成

@echo off
for /f "tokens=2 delims=," %%T in (myfile3.txt) do echo %%T
pause

如果想要同时筛选出第2列和第3列, 使用下面的脚本可以完成

@echo off
for /f "tokens=2,3 delims=," %%i in (myfile3.txt) do @echo %%i %%j
pause

for /f 命令读取文件时, 每一行作为一个元素, 然后该元素使用 delims 指定的分隔符进行分割, 使其由一行本文变成几个文本串, 文本串的索引从 1 开始。

例如 "第1行第1列,第1行第2列,第1行第3列" 这一行文本, 他被逗号分割成 3 个文本串,

第1个文本串:第1行第1列

第2个文本串:第1行第2列

第3个文本串:第1行第3列

tokens 选项的作用就是指定文本串的索引, 该选项的默认值为1。

tokens 选项可以指定多个索引,多个索引之间使用逗号分隔。

多个索引如果是连续的,比如tokens=1,2,3则可以简化成tokens=1-3,

部分连续也可以简化,比如tokens=2,5,6,7,9可以简化成tokens=2,5-7,9。

指定多个索引会导致额外变量名称的分配,tokens指定了多少个索引,就要分配多少个变量,

注意 tokens=1-3 是需要分配3个变量的,不能看做一个集合只分配一个变量。

另外额外的变量是按照英文字母的顺序分配的,如上例中 %%i 中被赋值第2个文本串, %%j被赋值第3个文本串。

按照字母顺序,i 后为 j,如果你将 %%j 改成 %%k 等非j的变量,都不会得到正确的输出。

如果想要显示所有被逗号分隔的文本, 使用下面的脚本可以完成

@echo off
for /f "tokens=1,2,3 delims=," %%i in (myfile3.txt) do @echo %%i %%j %%k
pause

或者

@echo off
for /f "tokens=* delims=," %%i in (myfile3.txt) do @echo %%i
pause

Note : 这里有一点注意,使用tokens=* 选项时,分隔符号也会被显示出来,这一点与 tokens=1,2,3 是不同的,tokens=1,2,3指定的文本串是以空格为间隔的。

tokens=* 表示该行所有的文本都赋值给%%i。

在tokens=*中, *也是需要分配变量的,再看一个例子tokens=2,3*,

同样*也是需要分配变量的,这个配置选项是这样工作的:

读取文件的一行,使用分隔符分隔出第一个文本串,不是需要的,继续分割出第二个文本串,是需要的,将其分配给%%i,

继续分割出第三个文本串,是需要的,将其分配给%%j,*代表该行剩余的文本,不用分隔,全都赋值给%%k,这也是使用*时会有分隔符的原因。

假设C盘根目录下有一个文件名字叫"myfile4.txt", 其中文件内容如下(在一些格式化的文件中有大量的数据,所以需要有一定的注释)

#这是第1个注释
第1行第1列,第1行第2列,第1行第3列
#这是第2个注释
第2行第1列,第2行第2列,第2行第3列
#这是第3个注释
第3行第1列,第3行第2列,第3行第3列

我们分析这个文件时,肯定是需要过滤掉注释,只分析有用的数据

@echo off
for /f "eol=# tokens=* delims=," %%i in (myfile4.txt) do @echo %%i
pause

选项eol表示忽略以某个字符开头的行,必须是单字符,并且该字符前不能有空格和TAB

假设C盘根目录下有一个文件名字叫"myfile5.txt", 其中文件内容如下(第1~2行是无用的)

NoUseLine1
NoUseLine2
#这是第1个注释
第1行第1列,第1行第2列,第1行第3列
#这是第2个注释
第2行第1列,第2行第2列,第2行第3列
#这是第3个注释
第3行第1列,第3行第2列,第3行第3列

处理这个文件时想要略过第1~2行

@echo off
for /f "eol=# skip=2 tokens=* delims=," %%i in (myfile5.txt) do @echo %%i
pause

选项 skip 指定在文件开始时忽略的行数。

2.4.1.2、处理字符串

处理字符串 其实相当于处理文件的一行,实际中直接应用较少, 一般应用于处理一个脚本中上面程序得出的结果。

@echo off
for /f "tokens=2,3 delims=," %%i in ("第1行第1列,第1行第2列,第1行第3列") do @echo %%i %%j
pause

2.4.1.3、处理命令结果

在命令行中输入set命令后回车,得到的是所有环境变量的值,例如 windir=C:\Windows,

如果我们想要显示所有的环境变量的名称可以使用下面的脚本

@echo off
for /f "tokens=1 delims==" %%i in ('set') do @echo %%i
pause

2.4.2、使用usebackq 选项

#使用 usebackq 选项,该选项在"options"中
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] # 处理文件, 文件名和路径中都可以有空格,必须用双引号括起来
FOR /F ["options"] %variable IN ('string') DO command [command-parameters] # 处理字符串, 要处理的字符串就是单引号括起来的内容
FOR /F ["options"] %variable IN (`command`) DO command [command-parameters] # 处理命令的结果, 在DO 后面的command执行之前先执行括号中用后引号括起来的命令,该命名的输出结果作为for的输入

2.4.2.1、处理文件

除了文件名(包含路径)中允许有空格,必须使用双引号括起来之外,与不使用usebackq没有区别

@echo off
for /f "usebackq" %%T in (“C:\Program Files\my file1.txt") do echo %%T
pause

2.4.2.2、处理字符串

与不使用usebackq选项的区别只是字符串使用单引号括起来,不使用双引号

@echo off
for /f "tokens=2,3 delims=, usebackq" %%i in ('第1行第1列,第1行第2列,第1行第3列') do @echo %%i %%j
pause

2.4.2.3、处理命令结果

与不使用usebackq选项的区别只是命令使用后引号括起来,不适用双引号

@echo off
for /f "tokens=1 delims== usebackq" %%i in (`set`) do @echo %%i
pause

2.4.3、使用 usebackq 选项与不使用 usebackq  选项的区别

处理内容 使用usebackq 不使用usebackq 备注
处理文件 文件名(含路径)必须使用双引号括起来 文件名(含路径)不能使用双引号括起来,文件名和路径中不能有空格 区别就是你使用的文件名中是否有空格,如果作为共通的处理,肯定要使用usebackq选项
处理字符串 字符串使用单引号括起来 字符串使用双引号括起来 引用符号不同
处理命令结果 命令使用后引号括起来 命令使用单引号括起来 引用符号不同

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3、FOR命令的进阶

稍微复杂一点的应用。

3.1、执行多条命令

看了上面的例子,你可能会发现, 每次for循环只能执行一条命令,这在实际应用中远远不够, 有什么方法像C语言中的for那样可以执行{}中的所有内容呢?

当然有那就是(), 需要注意的是 do 后要有空格然后跟着是"(" , 并且"(" 不可以另起一行。

@echo off
for /f "tokens=1 delims== usebackq" %%i in (`set`) do (
echo ------------------------------------------------
echo %%i
)
pause

3.2、变量的增强

In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:
FOR 变量参照的替换已被增强。您现在可以使用下列选项语法:
    %~I         # expands %I removing any surrounding quotes (") ;删除任何引号(")
%~fI # expands %I to a fully qualified path name ;将 %I 扩展到一个完全合格的路径名
%~dI # expands %I to a drive letter only ;仅将 %I 扩展到一个驱动器号
%~pI # expands %I to a path only ;仅将 %I 扩展到一个路径
%~nI # expands %I to a file name only ;仅将 %I 扩展到一个文件名
%~xI # expands %I to a file extension only ;仅将 %I 扩展为文件后缀名
%~sI # expanded path contains short names only ;将 %I 扩展到文件的文件属性
%~aI # expands %I to file attributes of file ;将 %I 扩展到文件的日期/时间
%~tI # expands %I to date/time of file ;将 %I 扩展到文件的大小
%~zI # expands %I to size of file ;将 %I 扩展到文件的大小
%~$PATH:I # searches the directories listed in the PATH environment variable
and expands %I to the fully qualified name of the first one found.
If the environment variable name is not defined or the file is not found by the search,
then this modifier expands to the empty string
;查找 PATH 环境变量中的目录,并将 %I 扩展到找到的第一个完全合格的名称。
如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串 The modifiers can be combined to get compound results:
可以组合修饰符来得到多重结果: %~dpI # expands %I to a drive letter and path only ;仅将 %I 扩展到一个驱动器号和路径
%~nxI # expands %I to a file name and extension only ;仅将 %I 扩展到一个文件名和扩展名
%~fsI # expands %I to a full path name with short names only ;仅将 %I 扩展到一个带有短名的完整路径名
%~dp$PATH:I # searches the directories listed in the PATH environment variable for %I and expands to the drive letter and path of the first one found.
;搜索列在路径环境变量的目录,并将 %I 扩展到找到的第一个驱动器号和路径。
%~ftzaI # expands %I to a DIR like output line ;将 %I 扩展到类似输出线路的 DIR In the above examples %I and PATH can be replaced by other valid
values. The %~ syntax is terminated by a valid FOR variable name.
Picking upper case variable names like %I makes it more readable and
avoids confusion with the modifiers, which are not case sensitive.
在以上例子中,%I 和 PATH 可用其他有效值代替。
%~ 遇到一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名比较易读,而且避免与不分大小写的组合键混淆。

C盘根目录下有以一个文件名字为"myfile.txt", 其内容如下:

"First", "Second","Thrid"

C:\Batch 文件夹下有名字为"test.bat"的脚本,其内容如下:

@echo offfor /f  "delims=, usebackq" %%T in ("C:\Program Files\my file.txt") do (
echo ---Original
echo %%T
echo ----expands %I removing any surrounding quotes
echo %%~T
echo ----expands %I to a fully qualified path name
echo %%~fT
echo ----expands %I to a drive letter only
echo %%~dT
echo ----expands %I to a path only
echo %%~pT
echo ----expands %I to a file name only
echo %%~nT
echo ----expanded path contains short names only
echo %%~sT echo ----expands %I to a drive letter and path only
echo %%~dpT
echo ----expands %I to a full path name with short names only
echo %%~fsT
echo ----expands %I to a file name and extension only
echo %%~nxT
echo ----expands %I to a DIR like output line
echo %%~ftzaT
)
pause

其运行结果如下:


---Original
"First"
----expands I removing any surrounding quotes
First
----expands I to a fully qualified path name
c:\Batch\First
----expands I to a drive letter only
c:
----expands I to a path only
\Batch\
----expands I to a file name only
First
----expanded path contains short names only
c:\Batch\First
----expands I to a drive letter and path only
c:\Batch\
----expands I to a full path name with short names only
c:\Batch\First
----expands I to a file name and extension only
First

 

注意: 扩展的路径是与脚本的路径有关的, 与脚本读取的文件路径无关,

另外,如果脚本所在的路径名有空格,其中几个命令的输出是有问题的,使用时,需要验证好.

没有在test.bat中列出的命令的输出是空的,具体的使用情况,我也没有细究,就到这里了...

上一篇:WordPress主题制作函数


下一篇:JavaScript数组入门。