Board logo

标题: [代码合集] 【原创】for命令-从入门到精通-简化版 [打印本页]

作者: 小程936    时间: 2016-6-2 22:17     标题: 【原创】for命令-从入门到精通-简化版

本帖最后由 小程936 于 2019-1-1 16:44 编辑

for命令-从入门到精通
(小程936原创,跟置顶帖没有一毛钱关系,我写这教程的时候根本不知道这个网站)

我相信大多数人对于for都是似懂非懂……主要原因就是,大部分教程求懒求快,直接复制for /?的机器翻译,导致基本没人看得懂,小部分教程堆砌辞藻,一句话能说完的事喜欢用不明觉厉的专业名称讲上几千字……本文承诺:绝不使用机器翻译帮助,不堆砌辞藻,祝大家学习愉快。

FOR函数,对一组文件批量执行命令,基本模式如下(ps:教程是给中国人看的,所以那种FOR %variable IN (set) DO command [command-parameters]教程写法我是绝对不会采用的)
1.文件搜索 for [/D] [/R [路径]] %%变量 in (集合) do (命令)
2.等差数列 for /L %%变量 in (开始,间隔,结束) do (命令)
3.文本处理 for /F ["选项"] %%变量 in (集合) do (命令)

注意:[A]表示可选,A|B表示多选,所以[方括号]和|符号是不用写到命令里的!
注意:【在批处理中使用 %%变量 ,在命令行中使用 %变量 ,记住了!】
详细的我们下一节再讲。
作业:按Win+R键运行cmd,输入以下命令试试(逐行复制,不要告诉我你连复制粘贴都不会),并试图理解for命令的写法
  1. @ echo&cd /d C:/
  2. for /D %i in (*) do echo %i
  3. for /L %a in (1,1,5) do (start cmd)
  4. for /F "delims=" %p in ('dir /as /b') do (echo %p)
复制代码




1.批量执行 for [/D] [/R [路径]] %%变量 in (集合) do (命令)

/D  只搜索文件夹名[可选],若无该选项即为 只搜索文件名
/R [路径]  搜索子目录[可选]
路径  搜索指定目录[可选](这个鸡肋参数要求必须开启 搜索子目录 才能用,若想指定搜索目录普遍做法是先用cd /d跳转目录)若无该选项即为 搜索当前目录
%%变量  可以是一个字母(不区分大小写),数字,或符号,用于在命令中使用,代表搜索结果。
集合  指定一个或一组文件。可以使用通配符搜索。(允许指定多个搜索条件 用空格分隔 "带空格 的搜索条件用双引号括住")(当搜索条件不包含通配符时 不搜索直接输出 因此也可以用来指定文本 用空格分隔 "带空格 文本用双引号括住")(通配符*表示0个或多个字符,通配符?表示0个或1个字符)
命令  指定批量执行的命令。使用%%变量 指定搜索结果。
  1. @ echo off
  2. for %%i in (*.bat) do (echo %%i)
  3. ::这段代码会显示当前文件夹(不含子文件夹)下所有的bat文件的文件名
  4. for %%i in (菜 芽 小 公 公) do echo %%i
  5. pause>nul
  6. ::这段代码会显示什么?试试看!
复制代码
注意:for搜索并不会搜索隐藏文件,因此若要搜索隐藏文件……过会儿再讲
作业:按Win+R键运行cmd,然后自行思索命令怎么写
1.搜索当前目录,目录名中包含es的目录,并显示出来
2.搜索子文件夹Desktop,包含子目录,并计算出该目录一共有多少文件。(set /a a+=1会用吧?不会就算了,显示出来也行)(本题不得使用cd跳转目录!)
3.分析下列代码,并尝试制作一个 [请输入多个数字,用空格隔开,输出这些数的乘积] 计算工具
  1. set c=1
  2. for %%i in (2 3 5 7 11 13 17 19 23 29 31 37) do set /a c*=%%i
复制代码






2.等差数列 for /L %%变量 in (开始,间隔,结束) do (命令)

(开始,间隔,结束)表示从开始到结束的一个数列,间隔为数列差。因此,(1,2,10)将产生序列
(1 3 5 7 9),(5,-1,1)将产生序列(5 4 3 2 1)

[命令行]连续打开10个cmd窗口。
  1. for /L %a in (1,1,10) do start cmd
复制代码
[批处理]生成一个100-200的数列,间隔为5
  1. for /L %%a in (100 5 200) do echo %%a
复制代码
这个命令很简单啦,没啥解释的
作业:使用for /L命令制作一个[阶乘计算工具](10的阶乘=10*9*8*7*……*2*1)

上期答案
1.
  1. for /D %i in (*es*) do (echo %i)
复制代码
2.
  1. for /R Desktop %i in (*) do set /a a+=1
复制代码
3.
  1. @echo off
  2. :1
  3. set /p a=请输入多个数字,用空格隔开=
  4. set c=1
  5. for %%i in (%a%) do set /a c*=%%i
  6. echo %a%的乘积=%c%
  7. goto 1
复制代码
答案仅供参考,不要求完全一致。
(楼主原创出品,刚刚写的)

上期答案
  1. @echo off
  2. :1
  3. set /p a=请输入数字=
  4. set c=1
  5. for /L %%i in (1,1,%a%) do set /a c*=%%i
  6. echo %a%的阶乘=%c%
  7. goto 1
  8. 答案仅供参考,不要求完全一致。
复制代码






3.文本处理 for /F ["选项"] %%变量 in (集合) do (命令)

我们先说说选项。多个选项用空格分开,整体必须用双引号括起来。示例:
  1. FOR /F "eol=; tokens=2,3* delims=," %%i in (myfile.txt) do @echo %%i %%j %%k
复制代码
可以使用的选项
eol=!  指定注释符号。默认未指定。(忽略以!开头的行)
skip=n  忽略第0-n行。默认为0(不忽略)
delims= -x 指定列分隔符,可指定多个。(将空格 减号-字母x指定为列分隔符)(默认分隔符为空格 制表符)(所谓制表符,打开记事本,按TAB键)
tokens=1,7-9* 读取第几列。默认为1。若命令为for /F "tokens=参数" %%a in (集合) do (命令)
当参数为1,7 变量a为第1列的内容,变量b为第7列的内容
当参数为7-9变量a为第7列的内容,变量b为第8列的内容,变量c为第9列的内容
当参数为9*变量a为第9列的内容,变量b为第9列之后所有列的内容
当参数为*变量a为所有列的内容。
当参数为1,7-9* 变量a为第1列的内容,变量b为第7列的内容,变量c为第8列的内容,变量d为第9列的内容,变量e为第9列之后所有列的内容。
看完这些,你已经明白tokens=怎么使用了吧?记住可用的三个符号,-*
usebackq 指定新语法。示范:for /F "usebackq" %%a in (集合) do (命令)
(集合) 指定一个或一组文件。可以使用通配符。(也可以指定文本或命令。)
usebackq 未启用  (一个或一组文本文档)   ("文本")    ('命令输出')
            (*.txt)     ("第一行 1,2 1,3 1,4") ('dir /as /b')
usebackq 已启用  ("一个或一组文本文档")   ('文本')    (`命令输出`)
            ("*.txt")     ('第一行 1,2 1,3 1,4') (`dir /as /b`)
"双引号" '单引号' `键盘上打不出来的某符号`
你可能觉得usebackq是一个可有可无,没有实际作用的选项?不要忘了,如果文件名中有空格,我们必须用双引号括起来!显然这会造成识别为文本……怎么办?启用usebackq呗~

额,说到这里,可能你还没弄懂for /F到底是啥……嗯,那就解释一下。
集合可以是  一个或一组文件(文本文档) 或 "引号括起来的文本" 或 '命令输出'
(*.txt) ("第一行 1,2 1,3 1,4") ('dir /as /b')
然后这些文本会逐行作为 %%变量 进行输出
使用上方的选项设置,可以做到……忽略以某符号开始的行 和 忽略开头的数行 和 指定列分割符 和 只读取每行中的指定列
多的不说,直接贴代码
  1. @echo off
  2. echo 第一行! 1,2 1,3 1,4 >test.txt
  3. echo 第二行! 2,2 2,3 2,4 >>test.txt
  4. echo 第三行! 3,2 3,3 3,4 >>test.txt
  5. echo 第四行! 4,2 4,3 4,4 >>test.txt
  6. echo 在当前文件夹下生成了一个test.txt,内容为:
  7. for /F "delims=" %%i in (test.txt) do echo %%i
  8. echo 这个文件的第一列是:&pause>nul
  9. for /F %%i in (test.txt) do echo %%i
  10. echo 这个文件的第二列是:&pause>nul
  11. for /F "tokens=2" %%i in (test.txt) do echo %%i
  12. echo 这个文件的第三和第四列是:&pause>nul
  13. for /F "tokens=3-4" %%a in (test.txt) do echo %%a %%b
  14. echo 这个文件的第二行是:&pause>nul
  15. for /F "skip=1 delims=" %%i in (test.txt) do echo %%i&goto 1
  16. :1
  17. pause&echo 一大波僵尸即将袭来&pause&tasklist
  18. echo 去掉以上内容的前三行,仅保留第一列 & pause>nul
  19. for /f "skip=3" %%i in ('tasklist') do echo,%%i
  20. pause>nul
  21. 作业:仔细理解完 上方代码,融会贯通,举一反三。
复制代码






变量扩展

大家知道,在cmd中执行for命令,变量用%i表示,而在bat中,变量用%%i表示。(这是为什么呢?学完这课大家就会懂了)
1.变量的范围
数字计算[±21 4748 3647 整数],文本[8191个字节](set /p a=<文件 和 ^换行符 可突破该限制,暂不解释)

2.变量的命名
不允许使用纯数字
不建议使用单字母变量
命名不区分大小写

3.变量扩展-文本(以下示例均以变量%a%示范,实际变量名可以为任何值)
%a:文本1=文本2% 文本1替换为文本2(文本2可留空,如%a:文本1=%)
%a:*文本1=文本2% 可使用通配符  *零个或多个任意字符  ?一个任意字符

%a:~10% 第10个字之后的内容
%a:~-10% 倒数第10个字之后的内容
%a:~,5% 开头之后的5个字
%a:~,-5% 倒数第5个字之前的字

%a:~10,5% 第10个字之后的5个字
%a:~10,-5% 第10个字之后,倒数第5个字之前的字
%a:~-10,5% 倒数第10个字之后的5个字
%a:~-10,-5% 倒数第10个字之后,倒数第5个字之前的字

%a:~列数,位数%,表示保留 指定列 之后的 指定位

123456789---列数----987654321-
   正数                 负数

注:文本扩展在for命令中可能不可用
示范:set a=%a:~-10,-5%

4.变量扩展-路径(以下示例均以变量%a示范)
(此时右边%可以省略, %~a 和 %~a% 是一样的)
%a 路径 "Temp\tmp 12345.txt"
%~a 删除引号 Temp\tmp 12345.txt
%~fa 完整路径 D:\AppData\Local\Temp\tmp 12345.txt
%~da 分区 D:
%~pa 路径 \AppData\Local\Temp\
%~na 文件名 tmp 12345
%~xa 扩展名 .txt
%~sa 短文件名 D:\AppData\Local\Temp\TM3A8C~1.TXT
%~aa 文件属性 --a--------
%~ta 修改日期 2016/06/02 16:26
%~za 文件大小(字节) 18
%~$b:a 在 目录b 搜索 文件a 找到的第一个文件。
如果变量b不存在,或者没有找到文件a,返回空字符串。
需事先给变量b赋值,多个路径可用分号分隔。命令示例
set b=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
可以组合使用来得到多重结果
%~dpa 分区和路径 D:\AppData\Local\Temp\
%~nxa 完整文件名 tmp 12345.txt
%~dp$b:a 在 目录b 搜索 文件a 输出 文件a 的 分区和路径
%~ftzaa 类似dir命令的输出(完整路径 日期 大小 属性)
--a-------- 2016/06/02 16:26 18 D:\AppData\Local\Temp\tmp 12345.txt
不组合拆分开也行,比如这样%~fa% %~ta% %~za% %~aa%
注意:路径扩展仅适用于%0 %1 …%9和for中的单字母变量%%i,若要支持其他变量,考虑使用call
  1. @echo off & set a=百度贴吧。百度公司。中国公司
  2. echo %%0 %0
  3. echo 文本
  4. echo %%a%% %a%
  5. echo %%a:。=-%% %a:。=-%
  6. echo %%a:百度=%% %a:百度=%
  7. echo %%a:*公司=123%% %a:*公司=123%
  8. echo %%a:~5%% %a:~5%
  9. echo %%a:~-5%% %a:~-5%
  10. echo %%a:~,3%% %a:~,3%
  11. echo %%a:~,-3%% %a:~,-3%
  12. echo %%a:~5,3%% %a:~5,3%
  13. echo %%a:~5,-3%% %a:~5,-3%
  14. echo %%a:~-5,3%% %a:~-5,3%
  15. echo %%a:~-5,-3%% %a:~-5,-3%
  16. pause & echo 产生一个临时文件>tmp^ 12345.txt
  17. rem 使用上方办法即可创建带空格的文件
  18. Call :sub "tmp 12345.txt"
  19. rem 以上一条命令表示跳转到sub标签并将变量%1设置为"tmp 12345.txt"
  20. pause & Del "tmp 12345.txt" & goto tu
  21. :sub
  22. echo 路径
  23. echo %%1 %1
  24. echo %%~1 %~1
  25. echo %%~f1 %~f1
  26. echo %%~d1 %~d1
  27. echo %%~p1 %~p1
  28. echo %%~n1 %~n1
  29. echo %%~x1 %~x1
  30. echo %%~s1 %~s1
  31. echo %%~a1 %~a1
  32. echo %%~t1 %~t1
  33. echo %%~z1 %~z1
  34. echo %%~dp1 %~dp1
  35. echo %%~nx1 %~nx1
  36. echo %%~ftza1 %~ftza1
  37. echo. & Goto :eof
  38. :tu
  39. echo 特殊变量
  40. echo 当前目录%%CD%% %CD%
  41. echo 当前日期%%DATE%% %DATE%
  42. echo 当前时间%%TIME%% %TIME%
  43. echo 范围在0-32767的伪随机数%%RANDOM%% %RANDOM%
  44. echo 错误返回码%%ERRORLEVEL%% %ERRORLEVEL%
  45. echo cmd的版本号%%CMDEXTVERSION%% %CMDEXTVERSION%
  46. echo 显示当前打开cmd所用的命令%%CMDCMDLINE%% %CMDCMDLINE%
  47. echo 当前最高NUMA节点号%%HIGHESTNUMANODENUMBER%% %HIGHESTNUMANODENUMBER%
  48. pause
复制代码
5.变量扩展-延迟(在批处理开头加上一行etlocal enabledelayedexpansion即可)
  1. @echo off
  2. set num=10
  3. set num=100 & echo %num%
  4. echo %num%
  5. echo 虽然已经将num的值更改为100,但由于没有延迟扩展,所以值仍为10,不过在下一个语句num的值就改变了
  6. pause
复制代码
  1. @echo off
  2. SetLocal EnableDelayedExpansion
  3. set num=10
  4. set num=100 & echo !num!
  5. echo 现在两个num的值一样了(注意%num%变成了!num!)
  6. echo %num%
  7. pause
复制代码
更复杂的写法
set q=!tem%c%!
set a=!aa:~%bb%,10!
set b=!a:%文本1%=%文本2%!

注意:延迟扩展与call的冲突
  1. @echo off&setlocal enabledelayedexpansion
  2. call :1
  3. echo %a%&pause
  4. :1
  5. setlocal enabledelayedexpansion&echo 运行一遍,然后删除本行,再运行一遍。
  6. set a=欢迎光临
  7. exit /b
复制代码
保留第五行,输出错误结果;删除第五行,输出正确结果 欢迎光临
结论:使用call跳转标签或文件时,需确保目标无“setlocal enabledelayedexpansion”,否则将产生错误
若必须保留setlocal enabledelayedexpansion这一行,可参考解决方案
  1. 方案1:
  2. @ echo off
  3. setlocal enabledelayedexpansion
  4. call :1 1
  5. echo %a%&pause
  6. :1
  7. if not #%*==# goto 2
  8. setlocal enabledelayedexpansion
  9. :2
  10. set a=欢迎光临
  11. exit /b
复制代码
  1. 方案2:
  2. @ echo off
  3. setlocal enabledelayedexpansion
  4. call :1
  5. for /F "delims=" %%i in (a) do set %%i
  6. echo %a%&pause
  7. :1
  8. setlocal enabledelayedexpansion
  9. set a=欢迎光临
  10. (set)>a
  11. goto :eof
复制代码






汇总小节

 for        [/D]   [/R       [路径]]  %%变量      in (集合)  do  (命令)
文件搜索 文件夹 子文件夹 指定目录 单字母   搜索/文本    批量

 for /L    %%变量 in (开始,间隔,结束)  do  (命令)
等差数列    单字母    开始,间隔,结束       批量

 for /F  ["选项"] %%变量  in    (集合)    do  (命令)
文本处理     选项  单字母       搜索/"文本"/'命令'    批量

 for /F "eol=! skip=n delims= -x tokens=1,7-9*    usebackq     "
选项   注释     行   分隔符     列         新语法("搜索"/'文本'/`命令`)

 %a:文本1=文本2% %a:~10,5% %CD% %DATE% %TIME% %RANDOM%
    替换              截取  当前目录  日期      时间    随机数





高级用法
1.文件搜索
可以指定多个搜索目标,用空格隔开,比如这样(for命令会对每个搜索目标都搜索一遍)
  1. for /D %i in (*es* a* Deskto?) do (echo %i)
复制代码
当没有搜索到目标时,输出搜索目标。因此for也支持 集合 内容为文本
  1. for %%i in (菜 芽 "小 公 公") do echo %%i
复制代码
3.文本处理
使用goto跳转,即可实现只读取一行。
  1. for /F "skip=3 delims=" %%i in (test.txt) do echo %%i&set a=%%i&goto 1
  2. :1
  3. for /F "skip=1 tokens=2 delims= " %%i in ('net user "%username%"') do set a=%%i&goto 2
  4. :2
  5. echo 中文用户名:%a: =%
复制代码
由于for /f支持读取 命令输出,所以for不能搜索隐藏文件的缺点可以借此部分修复。
  1. for /f "delims=" %%i in ('dir /ah /s/b') do attrib "%%i" -s -h -r
复制代码
:) :) :) :) :) :) :)



结束----------------------------欢迎点右下角的评分按钮↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
作者: kongfuzhou    时间: 2016-6-3 16:01

太赞了 先收藏
作者: jrx401    时间: 2016-7-2 01:28

可否有 如下部分的使用实例呢?
4.变量扩展-路径(以下示例均以变量%a示范)
%~$b:a 在 目录b 搜索 文件a 找到的第一个文件。
作者: 小程936    时间: 2019-1-1 16:17

本帖最后由 小程936 于 2019-1-1 16:28 编辑
可否有 如下部分的使用实例呢?
4.变量扩展-路径(以下示例均以变量%a示范)
%~$b:a 在 目录b 搜索 文件a 找 ...
jrx401 发表于 2016-7-2 01:28




   好的。
  1. md %temp%\tem233 2>nul
  2. cd /D %temp%\tem233
  3. md a  2>nul
  4. md b  2>nul
  5. echo 333>"b\文件.txt"
  6. rem 创建临时文件夹和文件
  7. rem
  8. set uu=%temp%\tem233\a;%temp%\tem233\b
  9. call :测试 文件.txt
  10. pause
  11. call :测试 文件5.txt
  12. pause
  13. cd /D %temp%
  14. rd /S /Q tem233
  15. cmd
  16. :测试
  17. @echo.---%~$uu:1---
  18. @exit /b
复制代码

作者: 小程936    时间: 2022-4-9 14:05

这么好的帖子没人看,可惜了
作者: Batcher    时间: 2022-4-9 21:49

感谢分享!
作者: karmane    时间: 2022-4-10 23:03

上等干货啊
作者: 小程936    时间: 2022-8-18 12:08


作者: fzp070    时间: 2022-8-21 23:01

学习了,讲解的非常好,赞!




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2