Windows Batch 4-10

Suppressing Program Output

pseudofile(伪文件)NUL是用来丢弃程序的输出的. e.g. 通过针对 loopback address调用 ping, 模拟Unix命令 sleep. 通过将 stdout重定向到 NUL设备来防止将 output打印到command prompt屏幕上.

PING 127.0.0.1 > NUL

Redirecting Program Output As Input to Another Program

假设你想要将程序的output链接起来作为input传送给另一个程序中. 这种方式被称为是 “piping”输出到另一个程序, 使用的是 pipe character(管道符) |.

e.g. 将DIR命令的输出进行排序:

DIR /B | SORT

A Cool Party Trick

可以通过command line重定向command prompt自己的 stdin来快速创建一个新的文本文件, 比如batch script: 调用 CON, 到一个文本文件; 使用 CTRL+Z来完成输入, 它会发送 end-of-file(EOF)字符:

TYPE CON > output.txt

[在 CTRL+Z之前需要输入换行]

DOS中有多种特殊文件可以重定向, 不过, 其中大部分是过时的, 如 LPT1 – parallel portt printers 或 COM1 for serial devices(串行设备) 像是 modem.

Part 5 – If/Then Conditionals

DOS对 if/then/else conditions有很好的支持.

Checking that a File or Folder Exists

IF EXIST "temp.txt" ECHO found

反之:

IF NOT EXIST "temp.txt" ECHO not found

两者都有:

IF EXIST "temp.txt" (
    ECHO found
) ELSE (
    ECHO not found
)

NOTE: 在两边的IF检查operands(操作数)上都加上引号是个好主意; 这可以防止麻烦的bug: 当变量不存在的时候, 会造成operand在事实上消失, 造成语法错误.

Checking If A Variable Is Not Set

IF "%var%"=="" (SET var=default value)

或者

IF NOT DEFINED var (SET var=default value)

Checking If a Variable Matches a Text String

SET var=Hello, World!

IF "%var%"=="Hello, World!" (
    ECHO found
)

或者大小写不敏感的比较:

IF /I "%var%"=="hello, world!" (
    ECHO found
)

[用 NOT表示 !]

Artimetic Comparisons

SET /A var=1

IF /I "%var%" EQU "1" ECHO equality with 1

IF /I "%var%" NEQ "0" ECHO inequality with 0

IF /I "%var%" GEQ "1" ECHO greater than or equal to 1

IF /I "%var%" LEQ "1" ECHO less than or equal to 1

[/A 表示表达式 expression]

Checking a Return Code

IF /I "%ERRORLEVEL%" NEQ "0" (
    ECHO execution failed
)

Part 6 – Loops

在collection(集合)中进行looping(循环)遍历是个常见任务, 可以对文件或目录进行循环, 或者对文本文件的每一行进行循环;

Old School with GOTO

old-school(老式的)lopping方法在早期DOS中是使用 label和 GOTO语句. 现在不多见了, 虽然它对command line参数的循环遍历还是有用的.

:args
SET arg=%~1
ECHO %arg%
SHIFT
GOTO :args

New School with FOR

对文件或文本进行循环遍历的现代方式是 FOR命令; FOR可以说是DOS中最有用的一个命令.

GOTCHA: FOR命令使用特殊的 %语法, 后面跟单个的字母, 比如 %I. 这个语法和 FOR在 batch文件中使用的时候稍有不同, 因为它需要额外的一个百分号, 或者 %%I. 在编写脚本的时候这是个常见的错误源头.

最好在遇到非法语句时退出循环, 确保你使用的是%%风格的变量

Looping Through Files

FOR %I IN (%USERPROFILE%\*) DO @ECHO %I

Looping Through Directories

FOR /D %I IN (%USERPROFILE%\*) DO @ECHO %I

递归地循环遍历 %TEMP%文件夹下面所有子文件夹下的文件:

FOR /R "%TEMP%" %I IN (*) DO @ECHO %I

递归地循环遍历%TEMP%文件夹下面所有子文件夹:

FOR /R "%TEMP%" /D %I IN (*) DO @ECHO %I

Variable Substitution for Filenames

[FOR %I IN (%USERPROFILE%*) DO @ECHO %I – 其中的 %I]

Part 7 – Functions

Function实际上是procedural (过程式)编程语言中代码重用的方式; 当DOS缺乏真正好用的 function关键字的时候, 可以利用 label和 CALL关键字来伪造一个.

gotchas:

1. quasi function(拟函数)要像label一样定义在脚本的末尾.

2. 脚本的主逻辑必须具备一个 EXIT /B [errorcode]语句; 这防止main logic(主逻辑)不会由于你的function失败而停止(fall through into).

[/B 退出当前脚本而不是退出 CMD.exe, 如果是在外部执行则退出 CMD.exe]

Defining a function

下例中, 会实现一个poor man版本的脚本: *nix tee utility – 将信息写到文件和stdout流中. 在function中使用一个对脚本来说 global的变量, %log%.

@ECHO OFF
SETLOCAL

:: script global variables
SET me=%~n0
SET log=%TEMP%\%me%.txt

:: The "main" logic of the script
IF EXIST "%log%" DELETE /Q %log% >NUL

:: do something cool, then log it
CALL :tee "%me%: Hello, world!"

:: force execution to quit at the end of the "main" logic
EXIT /B %ERRORLEVEL%

:: a function to write to a log file and write to stdout
:tee
ECHO %* >> "%log%"
ECHO %*
EXIT /B 0

Calling a function

使用 CALL关键字来调用 quasi function, 标签为 :tee; 可以像调用另一个batch文件一样在 command line上传递参数.

必须要记得在function底部加上 EXIT /B关键字; 遗憾的是, 除了返回exit code之外无法返回任何其他东西.

Return values

CALL的返回值总是function的 exit code. 就像其他可执行文件的调用一样, 调用者通过读取 %ERRORLEVEL%来获得 exit code.

可以有创造性地传递任何东西作为return code, 不仅仅是数字. function可以 ECHO到 stdout, 让调用者决定如何处理output, 将output作为input通过pipeling(管道传输)到另一个可执行文件, 重定向到文件或者通过 FOR命令解析.

调用者也可以通过修改 global变量来传递数据, 不过最好避免这种方式.

Part 8 – Parsing Input

强健的解析力是区分好脚本和了不起的脚本的分界线.

The Easy Way to read Command Line Arguments

目前为止解析command line参数的最简单方式是通过ordinal position(顺位)读取想要的参数.

这里我们从第一个参数获取到本地文件的路径. 如果文件不存在就写下错误消息, 退出脚本:

SET filepath=%~f1

IF NOT EXIST "%filepath%" (
    ECHO %~n0: file not found - %filepath% >&2
    EXIT /B 1
)

Optional parameters

给参数设置一个默认值

SET filepath=%dp0\default.txt

:: the first parameter is an optional filepath
IF EXIST "%~f1" SET filepath=%~f1

Switches

@ECHO OFF

SET /P COLOR="Choose a background color (type red, blue or black): "

2>NUL CALL :CASE_%COLOR% # jump to :CASE_red, :CASE_blue, etc.
IF ERRORLEVEL 1 CALL :DEFAULT_CASE # if label doesn‘t exist

ECHO Done.
EXIT /B

:CASE_red
  COLOR CF
  GOTO END_CASE
:CASE_blue
  COLOR 9F
  GOTO END_CASE
:CASE_black
  COLOR 0F
  GOTO END_CASE
:DEFAULT_CASE
  ECHO Unknown color "%COLOR%"
  GOTO END_CASE
:END_CASE
  VER > NUL # reset ERRORLEVEL
  GOTO :EOF # return from CALL

http://stackoverflow.com/questions/18423443/switch-statement-equivalent-in-windows-batch-file

Named Parameters

@ECHO OFF

SET man1=%1
SET man2=%2
SHIFT & SHIFT

:loop
IF NOT "%1"=="" (
    IF "%1"=="-username" (
        SET user=%2
        SHIFT
    )
    IF "%1"=="-otheroption" (
        SET other=%2
        SHIFT
    )
    SHIFT
    GOTO :loop
)

ECHO Man1 = %man1%
ECHO Man2 = %man2%
ECHO Username = %user%
ECHO Other option = %other%

REM ...do stuff here...

:theend

http://stackoverflow.com/questions/3973824/windows-bat-file-optional-argument-parsing

Variable Number of Arguments

myapp foo bar

shell

- # -> 2  
-* -> foo bar

- 0?>myapp?1 -> foo

- $2 -> bar

batch

- ?? -> 2 <—- what command?!

- %* -> foo bar

- %0 -> myapp

- %1 -> foo

- %2 -> bar

set argC=0
for %%x in (%*) do Set /A argC+=1
echo %argC%

https://en.wikibooks.org/wiki/Windows_Programming/Programming_CMD

Reading user input

:confirm
SET /P "Continue [y/n]>" %confirm%
FINDSTR /I "^(y|n|yes|no)$" > NUL || GOTO: confirm

Part 9 – Logging

在运行时和运行后都可以使用log工具来查错. 有时候比如在查看服务器端log的时候可能刷新太快来不及用肉眼观察, 此时, 一份简单的 log文件即可解决问题.

Log function

在Part7中有个基本的 tee实现:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS

:: script global variables
SET me=%~n0
SET log=%TEMP%\%me%.txt

:: The "main" logic of the script
IF EXIST "%log%" DELETE /Q %log% >NUL

:: do something cool, then log it
CALL :tee "%me%: Hello, world!"

:: force execution to quit at the end of the "main" logic
EXIT /B %ERRORLEVEL%

:: a function to write to a log file and write to stdout
:tee
ECHO %* >> "%log%"
ECHO %*
EXIT /B 0

这个tee quasi function可以把输出写到console(控制台)或者log文件中; 这里重用了 log文件路径, 保存在用户的 %TEMP%文件夹下面, 文件名为 batch文件名加上 .txt后缀.

如果想为每次执行都保留一份log, 可以简单地解析出 %DATE%%TIME%变量(利用command line扩展)来产生一个独特的文件名(至少在1秒钟的维度上是唯一的)

REM create a log file named [script].YYYYMMDDHHMMSS.txt
SET log=%TEMP%\%me%.%DATE:~10,4%_%DATE:~4,2%_%DATE:~7,2%%TIME:~0,2%_%TIME:~3,2%_%TIME:~6,2%.txt

除了从 *nix world学到的队列(queue)的方式, 这里还包含一个预定义的自定义output: script: some message. 这个技术对理清在有error的case中谁在complain极有帮助.

Displaying startup parameters

对于 non-interactive(非交互式)的脚本, 可以显示各种运行时的情况(runtime condition), 重定向到一个build log中.

现在还不知道是否有 DOS trick来辨别是 non-interactive会话还是 interactive会话; C#和 .Net有 System.Environment.UserInteractive属性来检测这种情况; *nix有些trick, 可以用 tty file descriptor(文件描述符).

或许可以hack一个方案, 通过观察custom environment variable(自定义环境变量), 比如 %MYSCRIPT_DEBUG% 默认是 false的.

http://stackoverflow.com/questions/8514735/what-is-special-about-dev-tty

Part 10 – Advanced Tricks

Boilplate info

建议在所有脚本都加上header, 记录 who/what/when/why/how. 可以使用 ::的注释技巧来描写文档:

:: Name:     MyScript.cmd
:: Purpose:  Configures the FooBar engine to run from a source control tree path
:: Author:   stevejansen[email protected]
:: Revision: March 2013 - initial version
::           April 2013 - added support for FooBar v2 switches

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

:: variables
SET me=%~n0

:END
ENDLOCAL
ECHO ON
@EXIT /B 0

Conditional commands based on success/failure

条件操作符 ||&&提供了方便的捷径来基于第一个命令的成功或失败来运行第二个命令.

&&语法是 AND操作符, 当第一个命令返回zero(成功)exit code时运行第二个命令.

DIR myfile.txt >NUL 2>&1 && TYPE myfile.txt

||语法是 OR操作符, 当第一个命令返回non-zero(失败)exit code时运行第二个命令.

DIR myfile.txt >NUL 2>&1 || CALL :WARNING file not found - myfile.txt

还可以组合两种方式. 注意如何使用 ()组来用 &&在第一个命令失败时, 创建运行两个命令的脚本:

DIR myfile.txt >NUL 2>&1 || (ECHO %me%: WARNING - file not found - myfile.txt >2 && EXIT /B 1)

Getting the full path to the parent directory of the script

:: variables
PUSHD "%~dp0" >NUL && SET root=%CD% && POPD >NUL

Making a script sleep for N seconds

使用 PING.EXE来伪造一个 *nix风格的 sleep命令.

:: sleep for 2 seconds
PING.EXE -N 2 127.0.0.1 > NUL

Supporting “double-click” execution (aka invoking from Windows Explorer)

测试 %CMDCMDLINE%是否和 %COMSPEC%相等. 如果相等, 就可以认为是允许在一个交互式对话中. 如果不相等, 可以在脚本的最后插入一个 PAUSE, 以显式output. 你可能需要目录改变到一个合法的工作目录中.

@ECHO OFF
SET interactive=0

ECHO %CMDCMDLINE% | FINDSTR /L %COMSPEC% >NUL 2>&1
IF %ERRORLEVEL% == 0 SET interactive=1

ECHO do work

IF "%interactive%"=="0" PAUSE
EXIT /B 0

—END—

—YCR—

时间: 2024-11-05 14:45:58

Windows Batch 4-10的相关文章

深入浅出Windows BATCH

1.什么是Windows BATCH BATCH也就是批处理文件,有时简称为BAT,是Windows平台上的一种可运行脚本,与*nix(Linux和Unix)上的Shell脚本和其它的脚本(Perl,Python)等是一样的,实质上就是一个文本文件,可是用特定的软件去解释的时候,就变成了可运行脚本.在Windows上,可运行脚本就是BATCH文件,也叫批处理文件,这是从DOS时代遗留下来的名字,意思就是把非常多命令放到一起来运行.它的扩展名是*.bat,双击便可直接运行,在命令行(CMD或叫做命

windows batch语法

windows BATCH基本知识扩展名是bat(在nt/2000/xp/2003下也可以是cmd)的文件就是批处理文件. ==== 注 =======================================.bat是dos下的批处理文件.cmd是nt内核命令行环境的另一种批处理文件从更广义的角度来看,unix的shell脚本以及其它操作系统甚至应用程序中由外壳进行解释执行的文本,都具有与批处理文件十分相似的作用,而且同样是由专用解释器以行为单位解释执行,这种文本形式更通用的称谓是脚本语

Windows Batch 1-4

Guide to Windows Batch Scripting http://steve-jansen.github.io/guides/windows-batch-scripting/index.html Overview batch可以帮助配置 DevOps , 提高每天的工作效率. Part 1 – Getting Started Launching the Command Prompt keyboard shortcut Windows Logo Key + R 输入cmd.exe E

windows xp,7,10,server 2003/2008下安装oracle 10g

在开发中我们经常用到oracle数据库.oracle现在有不同的版本,不同的项目由于开发时间不同而使用不同的oracle版本.由于各版本数据库功能存在不同,所以一但开发好后一般很难升级数据库版本.但我们所用的操作系统又在不断更新.许多人愿意尝试新的操作系统.由于操作系统兼容性的原因 ,oracle 10g在不同的Windows下的安装有一些不同. oracle 10g对Windows  XP 系统的兼容性最好,下载安装包之间双击运行即可. 在Windows server 2003中,直接双击运行

Cocos2d-x 3.x 开发(十八)10行代码看自动Batch,10行代码看自动剔除

1.概述 在游戏的运行过程中,图形的绘制是非常大的开销.对于良莠不齐的Android手机市场,绘制优化较好的游戏,可以在更多的手机上运行,因此也是优化的重中之重.图形方面的优化主要体现在减少GUP的绘制次数上.这里我们分别从自动优化渲染批次和绘制剔除两个方面来看新版本在绘制上的优化. 2.自动batch 在Cocos2d-x 3.x中,抛弃了先前手动编写BatchNode,采用自动管理的方式.说起BatchNode,就难免涉及到显卡底层的绘制原理.简单的说,每提交一条绘制指令到显卡都会产生消耗,

Build step &#39;Execute Windows batch command&#39; marked build as failure

坑爹的Jenkis,在执行windows命令编译.NET项目的时候命令执行成功了,但是却还是报了这样一个错: Build step 'Execute Windows batch command' marked build as failure 综合了几个stackoverflow上的答案,原因如下: jenkins执行windows命令,若退出代码不为0 ,则jenkins会将构建标记为失败 我解决的方法:在bat脚本最后一行加上 exit 0 Build step 'Execute Windo

windows和ubuntu 10.4双系统启动顺序

修改/boot/grub/grub.cfg文件 /boot/grub/grub.cfg文件,这与旧版本不同(9.10之前版本/boot/grub/menu.lst),而且为了安全起见,该文件默认为"只读"属性,因此在修改启动菜单之前你必须先将其文件属性改为"可读写"后方可修改文件内容. sudo chmod 666 /boot/grub/grub.cfg 修改成 default 4, 这里 的 数字 是根据 title行数来定. 你只要看到 menuentyr行 为

CCNET+ProGet+Windows Batch搭建全自动的内部包打包和推送及管理平台

所要用的工具: 1.CCNET(用于检测SVN有改动提交时自动构建,并运行nuget的自动打包和推送批处理) 2.ProGet(目前见到最好用的nuget内部包管理平台) 3.Windows Batch(windows的批处理,用于nuget的自动打包和推送)(这里是最难解决的地方) 具体的搭建步骤: 一.先搭建CCNET的持续集成环境,可以参照以下这些文章: http://www.cnblogs.com/jillzhang/archive/2008/03/03/1089099.html htt

jenkins 如何处理windows batch command

这两天一直被一个问题困扰. 在jenkins的windows batch command 测试好的,拿到bat文件中,再从Execute Windows Batch command 中调用这个bat,竟然离奇的报错了. 为什么呢? 先介绍一下场景和代码的逻辑.测试好的代码: CD %ROOTPATH%.\Tools\Bin\Python26\python. exe .\Tools\PythonScripts\SendMail.py %AUTOBUILD_PATH%\Charts [email p