WINDOWS BAT 批处理入门

  1. 批处理

    • 说明

      • 面向程序编程.
    • 实际

      • 提高效率.
    • 内容

      • 若干指令.
      • 需要反复执行.
      • 保存到文件中方便执行.
    • 启动cmd

      • C:\Windows\System32下双击cmd.exe指令.
      • Win+r输入cmd
      • win搜索cmd.
    • 特性

      功能 特点
      输入 交互式,实时决策执行.
      判断 for,if,while,switch都有.
      基本类型 数字,字符串,数组,函数
      匹配 正则表达式
      并发 默认串行,start并行.
      goto 指令跳转
      位运算 与或非
      逻辑运算 and or not,大于小于等于
      字符串 子串,长度,替换,裁剪
      文件 存在判断,修改属性,创建删除.
    • 延迟扩张

      • 两种解析:一种是读取一行就立即将%里面的变量解析.但是这类在一些场景不合适.
      • 另一种是延迟扩张:即在执行语句的时候扩张. 这样就允许组合表达式.
      • 类比makefilesecondexpansion.
  2. 脚本

    • 文件名后缀

      • BAT

      • CMD

    • 执行

      • BAT双击执行.
      • cmd中执行.
    • 执行bat

      • cmd中输入完整文件路径.
      • cmd => cd /path/to/bat => xxx.bat
      • 修改环境变量PATH=%PATH%;path\to\bat => 执行xxx.bat. (和上面两个一样的效果)
      • 路径下双击文件.
  3. 常用指令

    • 脚本

      指令 作用 案例
      ver 当前msdos版本. cmd启动时的第一行
      assoc 后缀绑定程序. .pdf默认用foxitreader打开.
      cls 清理屏幕 等价clear,cls清理屏幕和缓存
      path 环境变量,指定指令搜索路径. echo %path%
      rem remark,表示注释,不输出,啥也不做.
      start 并行执行 开启新的cmd窗口或程序
      driverquery 查看驱动详情
      ipconfig 网络信息管理,释放和重新分配.查看信息等.
      systeminfo 查看系统信息,系统信息,处理器,网卡,内存
    • 编程

      指令 作用 案例
      pause 暂停,等待输入任意符号. 常在脚本最后添加,查看执行输出.
      prompt 设置提示栏 默认情况下,输入前面是当前路径.$G == >
      choice 从给定的选择中任选一,一般是阿拉伯字母.
      title 命名窗口名称.
      set 查看已经定义的所有变量及值
    • 文件操作,不涉及目录

      指令 作用 案例
      copy 文件拷贝,不涉及路径拷贝
      del 文件删除,不涉及目录 支持嵌套递归.del /s *.txt
      attrib 修改文件属性 类似chmod.attrib +r file
      comp 比较两个文件的大小.
      more 查看文件内容
    • 目录操作

      指令 作用 案例
      cd 无参查看路径,有参更换路径. cd=pwd,cd xx=cd xx
      dir 查看路径下文件和文件夹 类似ls.支持查看子文件dir /s
      md 创建目录 类似mkdir,支持同时创建多个文件夹.
    • 文件和目录

      指令 作用 案例
      move 移动或重命名
      rd 默认仅仅删除文件夹,删除文件夹前不能为空./s删除文件 默认文件夹操作,选项支持文件操作.
      ren 重命名,文件夹和文件都支持.
      find 从文件中搜索字符串
      xcopy 文件和文件夹都支持,建议用这个. sh=cp
      tree 树形的方式查看文件夹子文件夹. tree可以分级,可以选择是否查看文件.默认仅查看目录.
    • 时间

      指令 作用 案例
      date 查看日期 echo %date%
      time 查看时间 echo $time%
    • 输出

      • 开关

        • echo on:输出执行的脚本。
        • echo off:不输出执行的脚本。
      • @

        • 从当前指令开始生效。
        • 一般用于@echo off.
  4. 代码

    • 创建修改

      • notepad打开,输入echo ok && pause,保存为xx.cmd或xxx.bat.
      • 点击文件,右键edit,编辑.
    • 命名

      • 尽量不要加空格.
      • 尽量不要和内部指令重名.
    • 执行和输出

      • 说明

        • 指的是在cmd中不要输出指令.
      • 普通

        指令
        dir /b
        
        输出
        D:\money\battst>ait.bat
        
        D:\money\battst>dir /b
        ait.bat
        dd
        good
        
        D:\money\battst>
        
      • 关闭指令输出

        关闭之后
        echo off
        dir /b
        
        输出
        D:\money\battst>ait.bat
        
        D:\money\battst>echo off
        ait.bat
        dd
        good
        
        D:\money\battst>
        

        echo off没有生效,执行后才生效所以输出了.
        dir /b生效了,没有输出指令.

      • 最终版本

        @echo off
        dir /b
        
        D:\money\battst>ait.bat
        ait.bat
        dd
        good
        
        D:\money\battst>
        

        最终版本,一条指令都没有输出.
        @就表示,echo off的影响从当前行开始.

    • 注释

      • 说明

        • 当一个批处理文件太大,往往是需要注释的.
      • 注释方式

        • :: comment
        • rem comment
  5. 变量

    • 来源

      • 两类: 参数类型变量,自动生成. 普通变量,自己定义.
    • 参数变量

      • 编号

        • %0 %1 %2 %3 ... %9,最多9个.
        • 可以通过SHIFT提升上限.即起始下标+1,args[0] = args[shift_time + 0].
        • 和普通程序一样.
      • 变量输出

        @echo off
        dir /b
        echo %0
        echo %1
        echo %2
        
        D:\money\battst>ait.bat 3 2
        ait.bat
        dd
        good
        ait.bat
        3
        2
        

        0是文件名,1,2就是参数.

      • 编号大于参数

        @echo off
        dir /b
        echo %0
        echo %1
        echo %2
        
        D:\money\battst>ait.bat 3
        ait.bat
        dd
        good
        ait.bat
        3
        ECHO 处于关闭状态。
        

        因为参数只有一个,echo %2的实际是echo,提示错误.

      • 提升上限.

        @echo off
        echo %0
        echo %1
        echo %10%
        shift
        echo %1
        shift
        echo %1
        shift
        echo %1
        shift
        echo %1
        
        D:\money\battst>ait.bat 99 88 77 66 55 44 33 22 11 46
        ait.bat
        99
        990
        88
        77
        66
        55
        

        shift一次,0-9指向的位置就+1.

    • set定义变量

      • 说明

        • set定义变量.
        • 默认定义字符型,加选项可以定义数字型.
        • 即加选项对后面的字符串进行不同的解析处理.
        • (会栈的也可以自己实现这种)
      • 字符定义和数字

        @echo off
        set aaa=1
        set /a bbb=%aaa% + %aaa%
        echo %aaa% %bbb%
        
        D:\money\battst>ait.bat
        1 2
        

        /a 则将后面替换后的的字符串进行算术解析.
        (怎么解析没有研究过.)
        aaa就是字符串,但是bbb的结果是字符串按照算术解析的方式得到的结果。

        字符串方式也可以定义数字,但是运算就需要用set /a的方式.
    • 作用域

      • 说明

        • 有局部变量和全局变量.setlocal之后,endlocal,exit,eof之前定义的都是局部变量,退出范围就恢复之前的值.
        • bat中的变量影响当前cmd,执行完了之后还在.
      • 案例

        @echo off
        set aaa=1
        setlocal enabledelayedexpansion
        set aaa=2
        echo %aaa%
        endlocal
        echo %aaa%
        
        

        注意aaa之前是1,局部输出2,endlocal之后恢复.

        D:\money\battst>ait.bat
        2
        1
        
      • 退出后无效

        这里改成ccc是因为aaa执行后在环境变量中已经有定义.set | find "aaa" 可查看.
        @echo off
        setlocal enabledelayedexpansion
        set ccc=2
        echo %ccc%
        endlocal
        echo %ccc%
        
        
        D:\money\battst>ait.bat
        2
        ECHO 处于关闭状态。
        
        • 之前演示的是定义后恢复值,这里演示退出后未定义.
    • 环境变量

      • set查看已经定义的.和具体值.访问和普通变量一样.
  6. 字符串

    • 说明

      • 全都是字符串.
      • set /a xxx = xxx + xxx的时候才进行算术运算,其他都是字符串操作.
    • 定义

      • 变量名和等号之间不能有空格.
      表达式 结果
      var = value var=之间有空格不行
      var= value 没有空格,行.
    • 字符串和数字

      @echo off
      set sss=2
      set /a bbb=%sss% * 5 + 1000
      echo %bbb%
      set ccc=%bbb% + 10
      echo %ccc%
      set /a ddd=%ccc%
      echo %ddd%
      echo %ddd:~2%
      
      D:\money\battst>ait.bat
      1010
      1010 + 10
      1020
      20
      
    • 值为空判断

      @echo off
      set sss= 
      if "%sss%" == "" (echo empty) else (echo not empty)
      set sss=
      if "%sss%" == "" (echo empty) else (echo not empty)
      
      D:\money\battst>ait.bat
      not empty
      empty
      
      第一个有个空格,第二个是真的空.
    • 子串

      @echo off
      set str=cool
      echo %str:~1%
      
      
      D:\money\battst>ait.bat
      ool
      
      • 子串格式说明

        功能 案例
        %str:~start,len% start起始位置,len长度. %str:~1,1% => o
        %str:~start% start起始位置,这个位置以后的所有. %str:~1% => ool
        %str:~start,-pos% start起始位置,-pos标示倒数第几个为止,不包含. %str:~1,-1% => oo
        %str:~-pos% -pos,从倒数第pos个起,包含. %str:~-1% => l
        %str:~-pos,len% -pos开始,长度为len的子串 %str:~-3,2% => oo
        %str:~-pos,-end -pos开始,到倒数第end的一个,end不包含. %str:~-3,-1% => oo
    • 替换

      @echo off
      set aaa=what the fuck
      echo %aaa%
      echo %aaa:fuck=f*k%
      
      D:\money\battst>ait.bat
      what the fuck
      what the f*k
      
    • 字符串长度

      rem @echo off
      set str=cool
      call :func_strlen str retlen
      echo %retlen%
      pause
      exit /b
      
      :: 函数定义
      
      :func_strlen
      setlocal enabledelayedexpansion
      :strLen_Loop
      if not "!%1:~%len%!" == "" set /a len+=1 & goto :strLen_Loop
      (endlocal & set %2=%len%)
      goto :eof
      
      

      bat没有求长度的函数,使用循环截取子串判断是否为字符串末尾.
      :func_strlen自定义函数定义.
      :srLen_Loop循环.
      :func_strlen函数定义.
      endlocal临时变量末尾
      set %2=%len%,给%2的变量名赋值.所以retlen有值.
      goto :eof返回,参考链接https://stackoverflow.com/questions/37515901/where-does-goto-eof-return-to.call :label会模拟创建一个新的bat文件再执行脚本,goto :eof就是退出文件,而这里是退出模拟文件,即返回了之前调用位置.
      exit /b不退出就会死循环,执行下面的函数并一直执行.及无限的调用函数退出.

      D:\money\battst>ait.bat
      
      D:\money\battst>rem @echo off
      
      D:\money\battst>set str=cool
      
      D:\money\battst>call :func_strlen str retlen
      
      D:\money\battst>setlocal enabledelayedexpansion
      
      D:\money\battst>if not "!str:~!" == "" set /a len+=1   & goto :strLen_Loop
      
      D:\money\battst>if not "!str:~1!" == "" set /a len+=1   & goto :strLen_Loop
      
      D:\money\battst>if not "!str:~2!" == "" set /a len+=1   & goto :strLen_Loop
      
      D:\money\battst>if not "!str:~3!" == "" set /a len+=1   & goto :strLen_Loop
      
      D:\money\battst>if not "!str:~4!" == "" set /a len+=1   & goto :strLen_Loop
      
      D:\money\battst>(endlocal   & set retlen=4 )
      
      D:\money\battst>goto :eof
      
      D:\money\battst>echo 4
      4
      
      D:\money\battst>pause
      请按任意键继续. . .
      
      D:\money\battst>exit /b
      
  7. 数组

    • 说明

      • 其实也是字符串,不过是字符串拼接.
      • 可以用set查看.
      • 不过多了这个编程概念,下标一般从0开始
    • 定义

      @echo off
      for /l %%i in (1,1,10) do set sss[%%i]=%%i
      set | find "sss"
      
      D:\money\battst>ait.bat
      sss[10]=10
      sss[1]=1
      sss[2]=2
      sss[3]=3
      sss[4]=4
      sss[5]=5
      sss[6]=6
      sss[7]=7
      sss[8]=8
      sss[9]=9
      
    • 遍历

      @echo off
      for /l %%i in (1,1,10) do set sss[%%i]=%%i
      set | find "sss"
      setlocal enabledelayedexpansion
      for /l %%i in (1,1,10) do echo !sss[%%i]!
      

      setlocal enabledelayedexpansion使用了延迟扩展,延迟扩展用!来表示.%在第一次的时候会扩展,而!则在第二次的时候进行扩展,

      D:\money\battst>ait.bat
      ssss=abcdefg
      sss[10]=10
      sss[1]=1
      sss[2]=2
      sss[3]=3
      sss[4]=4
      sss[5]=5
      sss[6]=6
      sss[7]=7
      sss[8]=8
      sss[9]=9
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
    • 长度

      数组需要从0定义,否则长度不准确.

      判断类似字符串,但是因为是变量,所以可以用关键字define.

    • 长度案例

      @echo off
      for /l %%i in (1,1,10) do set sss[%%i]=%%i
      setlocal enabledelayedexpansion
      for /l %%i in (1,1,100) do if defined sss[%%i] (set /a len+=1) else (goto :out)
      :out
      echo %len%
      
      
      D:\money\battst>ait.bat
      10
      

      **起始下表不是从0开始,其实不标准.

      扫描二维码关注公众号,回复: 13433306 查看本文章
  8. 决策

    • 解析

      • 按行解析,如果要多行,就要在行末尾表示行未结束.
      • 如何处理数字和字符串

        • 主要根据运算符有关.
        • 运算符决定了符号两边的解析方式.
      • if

        • 支持if,if else, if if等.
      • 变量操作

        • defined判断是否定义.
      • ==

        • 等于
      • errorlevel n

        • 上一次指令的退出嘛是否是n.n是自己的数字.
      • %errorlevel%

        • 上一条指令的返回值.
        • call可以一起用call other.cmd
      • goto

        • 跳转到指定的位置.
        • 注意call里面的goto.见前面.
    • 语法解析

      @echo off
      if 1 == 1 (echo nice) else (echo good)
      
      if 1 == 1 (echo nice) else (
      echo good)
      
      if 1 == 1 (
      echo nice
      ) else (
      echo good
      )
      
      if 1 == 1 (echo nice
      ) else (
      echo good)
      
      ::else
      ::(echo good)
      
      需要在行末尾表示行结束,else后啥都没有就是错误的.
  9. 运算符

    • 使用场景

      • 一般用于条件判断。
      • 不多也可以用于其他场景
    • 总览

      分类 说明
      数学运算 + - * / %,不支持浮点
      关系运算 >gtr;>=geq;==equ;<lss;<=leq;使用英文缩写,而不是>,<之类.==比较特殊. a < A,a < b,110 > 12.和字符值无关.数字按数字规则,字符串按字符串.
      逻辑运算 and or not,可以用于拼接bool表达式,即if.
      赋值运算符 += -= *= /= %=,算术运算.
      位运算 & | ^,与或异或.
      重定向 > >> < 2> 1> |
  10. 退出码

    • %errorlevel%
  11. 函数定义

    • 函数要素

      要素 说明
      声明 :function_name,和goto的位置标签一样.
      定义 若干个指令
      返回值 exit /b code返回
      获取返回值 %errorlevel%获取执行函数的返回值.
      参数赋值 endlocal & set %2=%var1%
      参数 call :func_name arg1 arg2 arg3
      获取参数 %1,%~1
    • exit /b

      • 仅仅退出批处理脚本,而不是退出cmd.exe
    • call :function_name | call cmd.bat

      • 调用函数,可以看成是在个新的cmd里面执行.
      • 但是变量会共享,所以一般会添加setlocal,endlocal.
      • 而且function里面可以定义:label.
      • 案例

        ::@echo off
        
        call :func_test 200 retlen
        echo %retlen%
        
        pause
        exit /b 2
        
        :func_test
        setlocal enabledelayedexpansion
        
        set /a dd=%1
        :while
        if %dd% gtr 0 (
            set /a dd/=10
            set /a cnt+=1
            goto :while
        )
        endlocal  & set %2=%cnt%
        goto :eof
        
        
        • 功能是判断一个数占几位.
        • endlocal & 是一句,会立即解析.
    • 局部变量

      • 在函数中,局部变量是很重要的.
      • 可以避免与外界变量冲突
    • 递归

      ::@echo off
      
      call :func_test 200
      echo %errorlevel%
      
      pause
      exit /b 2
      
      :func_test
      
      setlocal enabledelayedexpansion
      if %1% gtr 0 (
          set /a tmp=%1%/10
          call :func_test %tmp%
          set /a ret=!errorlevel!+1
          exit /b !ret!
      )
      
      
      • 和上面一样的功能,一样的结果.
      • 这里有enabledelayedexpansion才能执行成功,因为是执行的时候才扩张.
  12. 循环

    • 常见格式

      • for {%% | %}<variable> in (<set>) do <command> [<commandlineoptions>]
      • %%var%var的方式声明变量.
      • in固定格式。
      • (<set>),() 括号里面是集合,集合有很多种.
      • command循环体.
      • for in do固定格式.
    • set

      • 范围

        /l : loop,start,step,end.end包含.
        @echo off
        for /l %%i in (1,2,10) do ( echo %%i )
        
        D:\money\battst>ait.bat
        1
        3
        5
        7
        9
        
      • 路径/d : directory

        @echo off
        for /d %%i in (*) do ( echo %%i )
        
        D:\money\battst>ait.bat
        dd
        good
        
        路径
        D:\money\battst>tree
        D:.
        ├─dd
        └─good
        
      • 文件/r :recursive

        递归查看
        @echo off
        for /r %%i in (*) do ( echo "%%i")
        
        D:\money\battst>ait.bat
        "D:\money\battst\ait.bat"
        "D:\money\battst\aitd.bat"
        "D:\money\battst\dynamic_sub.bat"
        "D:\money\battst\dd\1.txt"
        
        D:\money\battst>tree /f
        卷 有钱人的固态 的文件夹 PATH 列表
        卷序列号为 DED3-62FD
        D:.
        │  ait.bat
        │  aitd.bat
        │  dynamic_sub.bat
        │
        ├─dd
        │      1.txt
        │
        └─good
        
    • 一般不用usebackq

      • 即在括号内用反括号当成是指令执行.
    • /f

      • 说明

        • 文件操作,按行读取,相关的开关进行按行解析.
      • 开关说明

        字段 说明
        eol eol开头的行忽略.
        skip n行忽略,前n行丢弃掉.
        delims 对一行数据进行拆分.默认分隔符是空格和tab.
        tokens 选择由delims分隔后的n个子串数组中的若干个.*;s-e;1,3,5,7,即指定选取的下标,可以是枚举,可以是区间,可以是*通配符.
        变量 tokens的时候,%%i则对应取到数据的下标1,%%j则对应2,%%k则对应3,一次类推.
        说明 都有默认值
      • 操作文件

        ,aa,bb,cc,dd,
        ,ee,ff,gg,hh,
        ,ii,jj,kk,ll,mm
        oo,pp,qq,rr,ss,tt
        
      • 文件查看

        @echo off
        for /f %%i in (aa.csv) do ( echo "%%i")
        
        D:\money\battst>ait.bat
        "aa,bb,cc,dd,"
        "ee,ff,gg,hh,"
        "ii,jj,kk,ll,mm"
        
      • eol;end of line

        @echo off
        for /f "eol=," %%i in (aa.csv) do ( echo "%%i" )
        
        D:\money\battst>ait.bat
        "oo,pp,qq,rr,ss,tt"
        
      • delims,tokens

        @echo off
        echo ------------------------------------
        for /f "delims=," %%i in (aa.csv) do ( echo "%%i")
        echo ------------------------------------
        for /f "delims=," %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l")
        echo ------------------------------------
        for /f "delims=, tokens=*" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l")
        echo ------------------------------------
        for /f "delims=, tokens=1-3,4" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l")
        echo ------------------------------------
        for /f "delims=, tokens=1-4" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l")
        
        
        D:\money\battst>ait.bat
        "aa"
        "ee"
        "ii"
        "oo"
        ------------------------------------
        "aa" "%j" "%k" "%l"
        "ee" "%j" "%k" "%l"
        "ii" "%j" "%k" "%l"
        "oo" "%j" "%k" "%l"
        ------------------------------------
        "aa,bb,cc,dd," "%j" "%k" "%l"
        "ee,ff,gg,hh," "%j" "%k" "%l"
        "ii,jj,kk,ll,mm" "%j" "%k" "%l"
        "oo,pp,qq,rr,ss,tt" "%j" "%k" "%l"
        ------------------------------------
        "aa" "bb" "cc" "dd"
        "ee" "ff" "gg" "hh"
        "ii" "jj" "kk" "ll"
        "oo" "pp" "qq" "rr"
        ------------------------------------
        "aa" "bb" "cc" "dd"
        "ee" "ff" "gg" "hh"
        "ii" "jj" "kk" "ll"
        "oo" "pp" "qq" "rr"
        
      • 分析

        None    = [0] = s.split(",")[0]
        *       = [0] = ",".join(s.split(","))
        range   = [:] = s.split(",")
        
      • (set)

        类型 说明
        (filename) 字符串来自文件. 可以多个文件
        "str" 字符串来自给定字符串
        'cmd' 字符串来自指令输出

猜你喜欢

转载自blog.csdn.net/rubikchen/article/details/121003820
今日推荐