Windows批处理文件有哪些鲜为人知但又重要且有用的功能?
指南:
每个答案一个功能
给出功能的简短描述和示例,而不仅仅是文档的链接
限制原生功能的答案,即不需要其他软件,如Windows资源工具包
澄清:我们在这里指的是由cmd.exe处理的脚本,这是WinNT变体的默认值.
(另请参阅:Windows批处理文件:.bat vs .cmd?)
线路延续:
call C:\WINDOWS\system32\ntbackup.exe ^ backup ^ /V:yes ^ /R:no ^ /RS:no ^ /HC:off ^ /M normal ^ /L:s ^ @daily.bks ^ /F daily.bkf
PUSHD path
转到path指定的目录.
POPD
带你回到你"推"的目录.
不确定这在批处理文件中有多大用处,但在命令提示符下使用它是一个非常方便的命令:
C:\some_directory> start .
这将在"some_directory"文件夹中打开Windows资源管理器.
我发现这是一个很好的节省时间.
我一直觉得很难阅读每行上用关键字标记的评论:
REM blah blah blah
更易于阅读:
:: blah blah blah
变量子串:
> set str=0123456789 > echo %str:~0,5% 01234 > echo %str:~-5,5% 56789 > echo %str:~3,-3% 3456
FOR命令!虽然我讨厌编写批处理文件,但我很感激.
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k
将解析myfile.txt中的每一行,忽略以分号开头的行,将第2和第3个标记从每行传递给for body,并用逗号和/或空格分隔标记.注意for body语句引用%i获取第二个标记,%j获取第三个标记,%k获取第3个标记之后的所有剩余标记.
您也可以使用它来迭代目录,目录内容等...
我没有在REM或:: lines中乱丢脚本,而是在每个脚本的顶部执行以下操作:
@echo OFF goto :START Description of the script. Usage: myscript -parm1|parm2 > result.txt :START
请注意如何使用管道和重定向字符而不转义它们.
脚本所在的路径(带驱动器):~dp0
set BAT_HOME=%~dp0 echo %BAT_HOME% cd %BAT_HOME%
已经提到了%~dp0片段,但实际上还有更多内容:〜之后的字符定义了提取的信息.
没有字母结果返回补丁文件名称
d - 返回驱动器号
p - 返回路径
s - 返回短路径
x - 返回文件扩展名
因此如果从c:\ Temp执行下面的脚本test.bat\long dir name \文件夹,
@echo off echo %0 echo %~d0 echo %~p0 echo %~dp0 echo %~x0 echo %~s0 echo %~sp0
你得到以下输出
test c: \Temp\long dir name\ c:\Temp\long dir name\ .bat c:\Temp\LONGDI~1\test.bat \Temp\LONGDI~1\
如果参数像
测试c:\ temp\mysrc\test.cpp
一样传递到脚本中,则可以使用%1变量完成相同的操作.
但是%0扩展的结果取决于位置!
在批处理的"顶层",它扩展为当前批处理文件名.
在函数(调用)中,它扩展为函数名称.
@echo off echo %0 call :test goto :eof :test echo %0 echo %~0 echo %~n0
输出是(批处理文件以myBatch.bat启动)
myBatch.bat :test :test myBatch
通过使用CALL,EXIT/B,SETLOCAL和ENDLOCAL,您可以使用局部变量实现子例程.
例:
@echo off set x=xxxxx call :sub 10 echo %x% exit /b :sub setlocal set /a x=%1 + 1 echo %x% endlocal exit /b
这将打印
11 xxxxx
即使:sub修改x.
偷偷摸摸的技巧等待N秒(不是cmd.exe的一部分,但因为它附带Windows而不是额外的软件),请参阅ping行.你需要N + 1 ping,因为第一次ping没有延迟.
echo %time% call :waitfor 5 echo %time% goto :eof :waitfor setlocal set /a "t = %1 + 1" >nul ping 127.0.0.1 -n %t% endlocal goto :eof
逃离"管道":
echo ^| ^< ^> ^& ^\ ^^
能够运行命令并处理输出(如bash中'$()'的反引号).
for /f %i in ('dir /on /b *.jpg') do echo --^> %i
如果文件名中有空格,请使用:
for /f "tokens=*" %i in ('dir /on /b *.jpg') do echo --^> %i
创建一个空文件:
> copy nul filename.ext
隐藏命令重定向到> nul 2>&1的所有输出.
例如,即使您重定向到> nul,某些命令行程序也会显示输出.但是,如果您将输出重定向到下面的行,则所有输出都将被抑制.
PSKILL NOTEPAD >nul 2>&1
编辑:请参阅忽略命令的输出以获取有关其工作原理的说明.
PAUSE
停止执行并显示以下提示:
Press any key to continue . . .
有用的,如果你想通过双击它在Windows资源管理器运行批处理,并希望见到实际的输出,而不是只是一个命令行窗口中闪光.
相当于bash(和其他shell)
echo -n Hello # or echo Hello\\c
输出" Hello
"没有尾随换行符.一个cmd hack来做到这一点:
set /p
是一种提示用户输入的方法.它发出给定的字符串然后等待(在同一行,即没有CRLF),以便用户键入响应.
只需管道对 set /p
命令的空响应,因此最终结果是发出的提示字符串.(由于空的响应,使用的变量保持不变.)问题是:输出一个前导等号是不可能的,并且在Vista上领先的空白字符被删除,但不是在XP上.
18> SqlACID..:设置环境变量时搜索和替换:
> @set fname=%date:/=%...从用于时间戳文件名的日期中删除"/".
和子串...
> @set dayofweek=%fname:~0,3%
19> Chris Noe..:整数算术:
> SET /A result=10/3 + 1 4
我的事情CMD.EXE的SET已经能够计算自NT 3.1左右.人们花了很长时间才注意到CMD.EXE与COMMAND.COM不完全相同......
20> doekman..:命令分隔符:
cls & dir copy a b && echo Success copy a b || echo Failure在第二行,&&仅在第一个命令成功时运行.
在第3行,||之后的命令 仅在第一个命令失败时运行.
21> paxdiablo..:输出一个空行:
echo.
22> 小智..:您可以链接if语句以获得类似短路布尔"和"的效果.
if foo if bar baz
23> RealHowTo..:快速将Unicode文本文件(16位/字符)转换为ASCII DOS文件(8位/字符).
C:\> type unicodeencoded.txt > dosencoded.txt作为奖励,如果可能,正确映射字符.
24> Ferruccio..:如果块结构:
if "%VS90COMNTOOLS%"=="" ( echo: Visual Studio 2008 is not installed exit /b )
只要你知道变量将一次性扩展(没有延迟扩展) - 即你不能合理地使用%ERRORLEVEL%.
@Duncan:你不应该使用伪变量`%ERRORLEVEL%`; 这就是`if errorlevel`的用途.并且**实际上在这些块中起作用.
25> paxdiablo..:变量的延迟扩展(带有子串以便进行测量):
@echo off setlocal enableextensions enabledelayedexpansion set full=/u01/users/pax :loop1 if not "!full:~-1!" == "/" ( set full2=!full:~-1!!full2! set full=!full:~,-1! goto :loop1 ) echo !full! endlocal
26> 小智..:不提供太多功能,但您可以将title命令用于几个用途,例如在任务栏中的长脚本上提供状态,或者只是为了增强用户反馈.
@title Searching for ... :: processing search @title preparing search results :: data processing
有趣.虽然此后你显然失去了常规功能,即显示当前运行的命令.有没有办法重置?
http://technet.microsoft.com/en-us/library/bb491017.aspx表示它可以自行重置"标题",但这似乎不适用于Windows 7 ...
27> MoreThanChao..:字符串减法的示例
date
和time
获取名为"YYYY-MM-DD HH:MM:SS.txt"的文件
echo test > "%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%_%time:~3,2%_%time:~6,2%.txt"
我
color
用来指示我的脚本是否成功,失败或需要通过更改文本和背景的颜色来输入.当你有一台机器可以看到你的视线但距离很远时,这确实很有帮助颜色XY
其中X和Y是从十六进制值
0
到F
,其中X -背景,Y -文本中,当X = Y颜色不会改变.颜色Z.
将文本颜色更改为"Z"并设置黑色背景,"颜色0"将不起作用
用于调用颜色的名称
颜色?
28> 小智..:没有编辑器方便,需要创建批处理文件?
copy con test.bat只需键入命令,按Enter键即可获得新行.按Ctrl-Z和Enter关闭文件.
嘿,这让我回来了.
29> paxdiablo..:使用间距和转义字符对输出进行完全控制:
echo. ^/%basedir%/resources^
"echo.x"将输出"x","echo x"将仅输出"x".这允许前导空间.此外,"^"转义字符将阻止cmd认为所有那些"<"和">"字符都是I/O重定向.
30> 小智..:TheSoftwareJedi已经提到了for命令,但是我会再次提到它,因为它非常强大.
以下以YYYYMMDD格式输出当前日期,我在生成备份目录时使用它.
for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a
它过度使用FOR,imo.我想我只会使用%DATE:~10,4 %% DATE:~4,2 %% DATE:~7,2%,而不是运行日期命令然后解析它.
当然DATE/T在欧洲和2008年10月29日在美国的29/10/2008返回...所以可能需要一些本地化!;-)
31> Lara Dougan..:您可以使用call来稍后评估名称,从而产生一些有用的属性.
call set SomeEnvVariable_%extension%=%%%somevalue%%%使用call来设置名称取决于其他变量的变量.如果与某些变量命名规则一起使用,则可以使用仔细的命名规则来模拟数组(如数组或字典).在某个值周围的三重%是如此,它将在调用之后和调用set之前评估为由单个%包围的一个变量名.这意味着连续两个%转义为单个%字符,然后它会再次展开它,因此somevalue实际上是一个名称指针.
call set TempVar=%%SomeEnvVariable_%extension%%%将它与temp变量一起使用以检索该值,然后可以在逻辑中使用该值.当与延迟变量扩展一起使用时,这最有用.
要正确使用此方法,需要启用延迟变量扩展.因为它默认是关闭的,所以最好在脚本中启用它,方法是将其作为第一条指令之一:
setlocal EnableDelayedExpansion
32> paxdiablo..:在路径上搜索可执行文件(或者在必要时搜索其他类似路径的字符串):
c:\> for %i in (cmd.exe) do @echo. %~$PATH:i C:\WINDOWS\system32\cmd.exe c:\> for %i in (python.exe) do @echo. %~$PATH:i C:\Python25\python.exe c:\>
33> matt wilkie..:关于使用
::
而不是REM
评论:小心!::
是一个CALL标签的特例,其作用类似于注释.当在括号内使用时,例如在FOR或IF循环中,该函数将过早退出.调试非常令人沮丧!有关完整说明,请访问http://www.ss64.com/nt/rem.html.
(在第一次提到上述内容时添加新答案而不是评论,因为我不值得赞扬:0)
34> Coding With ..:这些天很多人使用GOTO:EOF来终止他们的批处理文件,但你也可以使用EXIT/B来实现这个目的.
使用EXIT/B的优点是你可以在EXIT/B之后添加一个错误级别,它将以错误级别退出.
35> Coding With ..:仍然会为ENDLOCAL使用的行解析局部变量.这允许像下面这样的技巧:
ENDLOCAL & SET MYGLOBAL=%SOMELOCAL% & SET MYOTHERGLOBAL=%SOMEOTHERLOCAL%这是将结果传输到调用上下文的有用方法.具体来说,一旦ENDLOCAL完成,%SOMELOCAL%就会超出范围,但到那时%SOMELOCAL%已经展开,因此MYGLOBAL在调用上下文中使用局部变量进行分配.
出于同样的原因,如果您决定这样做:
ENDLOCAL & SET MYLOCAL=%MYLOCAL%您将发现新的MYLOCAL变量实际上是作为常规环境变量而不是您可能想要的本地化变量.
36> paxdiablo..:子程序(输出42):
@echo off call :answer 42 goto :eof :do_something echo %1 goto :eof和子程序返回一个值(输出0,1,2等):
@echo off setlocal enableextensions enabledelayedexpansion call :seq_init seq1 :loop1 if not %seq1%== 10 ( call :seq_next seq1 echo !seq1! goto :loop1 ) endlocal goto :eof :seq_init set /a "%1 = -1" goto :eof :seq_next set /a "seq_next_tmp1 = %1" set /a "%1 = %seq_next_tmp1% + 1" set seq_next_tmp1= goto :eof
37> 小智..:cmd.exe中的快速编辑模式是我的最爱.这稍微偏离了主题,但是当与命令shell交互时,它可以成为救生员.不,我不是双曲线 - 在你死之前你只会看到一些次数的插入符号 ; 你看得越多,你死得越快.
打开注册表(小心,不是我的错,蓝屏等)
转到HKCU/Console
将QuickEdit设置为1
(你也可以在UI中设置这个,这可能是更好的方法.请参阅注释以获取说明.还有一个很好的单行脚本也可以这样做.)
现在,要复制,只需单击鼠标左键并拖动即可选择并右键单击进行复制.要粘贴,只需右键单击即可.
没有更多的时间^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V ^ V !!!
废话,我想我刚刚杀了一个人.抱歉!
您无需直接编辑注册表即可设置此项.单击窗口左上角的命令提示符图标.选择属性.在"选项"选项卡上,选中"快速编辑模式"框.
38> Andy Morris..:调用集 - 将环境变量扩展到几个级别.
在http://ss64.com/nt/call.html#advanced找到这个从回答另一个SO问题批量文件变量在for循环中初始化
set VarName=Param set Param=This call set Answer=%%%Varname%%% Echo %Answer%给
set VarName=Param set Param=This call set Answer=%Param% Echo This This