为了顺应当前形势和更好的发展,黑基网已于9月19日正式更名为【安基网】,域名更换为www.safebase.cn,请卸载旧的APP并安装新的APP,给您带来不便,敬请理解!谢谢

黑基Web安全攻防班
安基网 首页 IT技术 电脑技术 查看内容

Windows 批处理经验总结

2018-9-6 07:50| 投稿: xiaotiger |来自: 互联网

摘要: 批处理 (.bat,.cmd) 是 Windows 系统上古老的脚本语言,其后又有 PowerShell 等脚本出现,虽然批处理的应用已经渐渐减少,但是仍有许多旧有的批处理脚本需要维护。这里记录了我在处理批处理时的一些经验总结,包含了 ...

批处理 (.bat.cmd) 是 Windows 系统上古老的脚本语言,其后又有 PowerShell 等脚本出现,虽然批处理的应用已经渐渐减少,但是仍有许多旧有的批处理脚本需要维护。这里记录了我在处理批处理时的一些经验总结,包含了资料手册最佳实践经验技巧陷阱与缺陷以及常用代码片段五个部分。

资料手册

最佳实践

  • 将批处理中定义的变量局限于批处理中,避免污染批处理调用者的环境。

    SETLOCAL
    ...
    ENDLOCAL
    

    其中 ENDLOCAL 是可选的,当执行到批处理文件末的时候,默认就是 ENDLOCAL

  • 比较变量时,为其加上引号,避免空字符串或含空白符的字符串等造成语法或语义上的错误。

    REM 如果一个变量被赋值为空字符串,或未被定义,
    REM 在两种情况下,这个变量在批处理中都会被展开为空字符串。
    SET foo=
    IF "%foo%" == "bar" echo 逻辑可以正常执行
    IF %foo% == bar echo 执行会报错
    	
    SET dir=a b
    REM 以下语句会创建 a, b 两个文件夹
    mkdir %dir%
    REM 以下语句只会创建 a b 这一个文件夹
    mkdir "%dir%"
    
  • 使用 REM 来添加对于 debug 有帮助的信息或文本,使用 @REM 或 :: 来添加 debug 时不需要,但提供其他信息的注释文本。

    编写批处理时,我们通常会在批处理顶部加上 @echo off 以关闭命令回显,而在 debug 时,我们通常会删掉或注释此行。此时,添加在 REM 后的注释信息,也会被打印到屏幕上,如果这些信息对于 debug 有帮助的话,则是合适的;如果 debug 时不需要这些信息的话,则应该使用 @REM 或 :: 来注释,这样在开启命令回显时,也不会被打印出来。

  • 把对于 GOTO 标签的注释放在标签后,这样可以在 debug (echo on) 的时候看到该标签相关的注释信息。

    :Label
    REM Label 相关的注释
    REM ...
    
  • 使用 pushdpopd 切换目录。

    在批处理中使用 pushd popd 来切换目录,保证在正常退出批处理时,用户所在的目录不会因为执行批处理而被改变。

    pushd dir1
        echo Do this
        echo Do that
    
        pushd dir2
            echo Do other stuff
        popd
    popd
    

    另外,对 pushd 和 popd 中的代码进行适当的缩进,可以显著提高代码的可阅读性。

  • 使用 GOTO Label 而不是 GOTO :Label

    对于大部分 GOTO 标签来说,GOTO Label 与 GOTO :Label 是等效的。

    有一个例外则是 EOF 标签,GOTO EOF 与 GOTO :EOF 有着不同的意思。其中 GOTO EOF 跳转到用户定义的 EOF 标签,而 GOTO :EOF 则是跳转到批处理文件的末尾。

    所以,为了保持一致性,使用 GOTO Label 来跳转到用户定义的标签,只在跳转到批处理末时使用 GOTO :EOF

  • 不要定义名为 EOF 的标签。

    由于已有在 CMD 中预定义的 :EOF 标签,所以尽管在代码中可以区分预定义的 :EOF 标签与自定义的 EOF 标签,最好还是避免去自定义 EOF 标签,以免造成混淆。

  • 总是使用 cmd /c 来调用外部批处理,除非期望外部批处理改变当前执行中的批处理的变量时才使用 CALL 来调用外部批处理。

    由于 CALL 会引入被调用批处理对变量的改变,而 cmd /c 则不会。因此我们看到 cmd /c 时,就可以有自信调用者所在的批处理中的变量不会因为调用外部批处理而被改变。

  • 永远使用 %~dp0\dir 来访问相对于被调用批处理所在位置的文件。

    使用 %~dp0\dir 而不是 .\dir 或者 dir 形式来访问相对于被调用批处理所在位置的文件,可以保证批处理无论是双击执行,还是通过 cmd 在批处理所在文件夹中执行,或是通过 cmd 在任意文件夹中执行时,都能访问到正确的文件。

    %~dp0 与 linux shell 中的 dirname "$0" 是相对应的。

  • 避免使用路径格式符 (a, d, f, n, p, s, t, x) 作为 for 循环的循环变量名。

    FOR %%G IN (C:\Windows\*) DO echo %%~nG
    

    以免在对循环变量做路径格式处理时造成阅读上的混淆。

经验技巧

  • :label 标签后 (空格)\t (制表符): (冒号) 字符后的内容会被忽略。

    因而我们可以在 :label 后添加注释,或一些对于编辑器有用的标记符号。

    如 vim 中的代码折叠标记为 {{{ 符号,我们就可以将其添加在 :label 标签后,来创建一个折叠片段。

    :label {{{
    echo ...
    

陷阱与缺陷

  • 对批处理使用 ANSI 编码,CRLF 换行符。

    如果批处理中包含非 ASCII 字符,那么务必需要对批处理使用 ANSI 编码,而不是 UTF-8,或其他 OEM 字符集,否则会导致批处理运行异常。

    同样的,批处理文件无论如何都应该使用 CRLF (\r\n) 换行符,否则可能导致批处理运行异常。

  • 转义不同字符的引导字符是不同的。

    下表列出了在批处理中所有可能需要转义的字符:

    被转义字符转义形式意义
    ^转义空格,从而避免使用引号。
    如:C:\Program^ Files\Notepad++\notepad++.exe
    %%%使用变量。
    ^^^转义字符本身。
    &^&& - 依次执行两条命令;
    && - 若前一条命令执行成功(返回 0),则执行后一条命令。
    <^<重定向输入。
    >^>重定向输出。
    |^|| - 管道输出;
    || - 若前一条命令执行失败(返回非 0),则执行后一条命令。
    )^)用于 IF, FOR 等语句的 () 中时,需要转义。 (*)
    换行符^ + 换行符将一条较长的命令分为多行书写。

    (*) 值得注意的是,即使 ) 是保存在变量(%var%)中的,如果该变量被用在一组括号中,则仍需对其进行转义。

  • 在 cmd 中与在批处理中执行代码的不同:

    • 批处理中 for 循环的循环变量采用 %%G 的形式,而直接在 cmd 中执行的 for 循环的循环变量采用 %G 的形式。

    • 批处理中不存在的变量会被展开为空字符串,而在 cmd 中不存在的变量则不会被展开。

      分别在命令行中和批处理中执行以下命令来验证:

      echo %nonexistent%
      
  • 使用变量替换时务必确认变量已被定义。

    所谓变量替换指对变量中的字符串进行查找替换或删除,语法如下:

    %variable:StrToFind=NewStr%
    

    例:

    set foo=ABCDEFGHI
    
    echo %foo:DEF=%
    rem 以上语句输出 ABCGHI
    
    echo %foo:DEF=def%
    rem 以上语句输出 ABCdefGHI
    

    但是如果要替换的变量未定义的话,输出结果就不会是所期望的空字符串,如下所示(注该例子需编写 .bat 脚本后执行验证):

    set foo=
    
    echo %foo:DEF=%
    rem 以上语句输出 DEF=
    
    echo %foo:DEF=def%
    rem 以上语句输出 DEF=def
    

    因此,作变量替换时,务必确认该变量已定义:

    IF DEFINDED foo (
        echo 变量 foo 已定义
    )
    
  • FOR 循环的循环变量只能采用单字母的名字。

  • FOR 循环的循环变量名是大小写敏感的。

    Windows 下的名字多为大小写不敏感的,如:

    • 路径 C:\WINDOWS 与 c:\windows 是等效的;
    • 命令及其参数 ECHO ON 与 echo on 是等效的;
    • 变量名 %WINDIR% 与 %windir% 是等效的;

    然而在批处理中有个例外是 for 循环的循环变量,%%G 与 %%g 是不同的。

  • FOR 循环 IN 语句中重定向输出需要转义。

    否则会报语法错误:> was unexpected at this time. 或 2> was unexpected at this time.

    正确形式如下:

    小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!
    

    本文出自:https://zzz.buzz/zh/notes/windows-batch/

    免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

最新

返回顶部