当前位置:  开发笔记 > 编程语言 > 正文

Windows批处理文件的隐藏功能

如何解决《Windows批处理文件的隐藏功能》经验,为你挑选了38个好方法。

Windows批处理文件有哪些鲜为人知但又重要且有用的功能?

指南:

每个答案一个功能

给出功能的简短描述示例,而不仅仅是文档的链接

限制原生功能的答案,即不需要其他软件,如Windows资源工具包

澄清:我们在这里指的是由cmd.exe处理的脚本,这是WinNT变体的默认值.

(另请参阅:Windows批处理文件:.bat vs .cmd?)



1> Chris Noe..:

线路延续:

call C:\WINDOWS\system32\ntbackup.exe ^
    backup ^
    /V:yes ^
    /R:no ^
    /RS:no ^
    /HC:off ^
    /M normal ^
    /L:s ^
    @daily.bks ^
    /F daily.bkf


^实际上是一个引用字符.使用它,您可以引用<和>,以便它们不会重定向输出.行末尾的^也允许行继续.
我上周正在寻找这个!(不记得这个角色)
@furtelwart:这就像你把所有内容写成一行一样:`call C:\ WINDOWS\system32 \ntbackup.exe backup/V:yes/R:no/RS:no/HC:off/M normal/L:s @ daily.bks/F daily.bkf`.要了解该行的所有参数,只需运行`C:\ WINDOWS\system32 \ntbackup.exe /?`.

2> raven..:
PUSHD path

转到path指定的目录.

POPD

带你回到你"推"的目录.


如果您推送到UNC路径,它将自动为您映射驱动器,popd将取消映射它.
这也可以作为一个完整的堆栈,因此你可以将许多目录推入堆栈,然后继续弹出以回到原来的位置.
运行'cmd.exe'然后输入'help',然后输入'help pushd'或'pushd /?'.
特别是对于UNC功能+1,您应该将其添加到您的答案中.

3> LeopardSkinP..:

不确定这在批处理文件中有多大用处,但在命令提示符下使用它是一个非常方便的命令:

C:\some_directory> start .

这将在"some_directory"文件夹中打开Windows资源管理器.

我发现这是一个很好的节省时间.


'explorer'也和'start'C:\ some_directory> explorer一样.

4> Chris Noe..:

我一直觉得很难阅读每行上用关键字标记的评论:

REM blah blah blah

更易于阅读:

:: blah blah blah


事实上,::只是一个有趣名字的标签; 因此,如果你在一个块内(在括号中)使用它将不起作用,因为那里也不允许标签.REM当然在那里工作.
我听说::比REM更有效,因为REM试图对它之后发生的事情进行环境变量扩展,但是::没有.

5> Chris Noe..:

变量子串:

> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456


丑陋,但很有用!

6> TheSoftwareJ..:

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个标记之后的所有剩余标记.

您也可以使用它来迭代目录,目录内容等...


未充分利用与否,这是折磨.(有些人认为必要的邪恶.)
我发现批处理文件'FOR循环有限且写得很糟糕,但它们有时很有用.
请原谅我的困惑,但这究竟是如何未被充分利用的呢?我想如果你不知道FOR循环,你不知道批处理脚本.

7> Patrick Cuff..:

我没有在REM或:: lines中乱丢脚本,而是在每个脚本的顶部执行以下操作:

@echo OFF
goto :START

Description of the script.

Usage:
   myscript -parm1|parm2 > result.txt

:START

请注意如何使用管道和重定向字符而不转义它们.


嗯,有文化的批量编程?!
如果你检查%1为"/?"会更酷吗?然后你可以将该部分作为帮助文本回显.

8> RealHowTo..:

脚本所在的路径(带驱动器):~dp0

set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%


%CD%是当前目录,而%~dp0是运行脚本所在的目录.

9> 小智..:

已经提到了%~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



10> Ferruccio..:

通过使用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.


你应该使用goto:eof而不是exit/b,做同样的事情,但是更标准的方法.
我发现最好使用"exit/B"而不是"goto:eof"从子程序返回,"goto:eof"有一个问题,当你想要吞下它时你可能会返回一个错误代码.例如,如果您使用"如果存在someFile回显它在这里",这将设置errorlevel如果someFile不存在,但这没有错,并且不是您想要返回的错误代码(这是什么"转到:eof"会这样做".
我的错.我认为你的意思是明确定义一个:eof标签并对其进行转换.我没有意识到每个批处理文件末尾都有一个隐含的:eof标签.
但是,如果您希望子例程设置errorlevel,则需要使用exit/b.例如:exit/b 3
这有一个标准吗?O_O

11> paxdiablo..:

偷偷摸摸的技巧等待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


更好的是把它放在像sleep.bat这样的文件中,以免你一遍又一遍地重写它.

12> Chris Noe..:

逃离"管道":

echo ^| ^< ^> ^& ^\ ^^


啊,这就解释了为什么它也是行继续运算符 - 它逃脱了换行符,就像在bash中一样......
我敢打赌,DOS转义字符并不为人所知.好的.

13> paxdiablo..:

能够运行命令并处理输出(如bash中'$()'的反引号).

for /f %i in ('dir /on /b *.jpg') do echo --^> %i

如果文件名中有空格,请使用:

for /f "tokens=*" %i in ('dir /on /b *.jpg') do echo --^> %i


不适用于名称中包含空格的文件名...这有效:for/f"tokens =*"%i in('dir/on/b*.jpg')做回声 - ^>%i

14> nzpcmad..:

创建一个空文件:

> copy nul filename.ext


@devio:回声.放空行.所以文件不会是空的!
我使用`type nul> filename.ext`.

15> aphoria..:

隐藏命令重定向到> nul 2>&1的所有输出.

例如,即使您重定向到> nul,某些命令行程序也会显示输出.但是,如果您将输出重定向到下面的行,则所有输出都将被抑制.

PSKILL NOTEPAD >nul 2>&1

编辑:请参阅忽略命令的输出以获取有关其工作原理的说明.


> nul将STDOUT重定向到nul.2>&1将STDERR重定向到STDOUT指向的任何位置.

16> raven..:
PAUSE

停止执行并显示以下提示:

Press any key to continue . . .

有用的,如果你想通过双击它在Windows资源管理器运行批处理,并希望见到实际的输出,而不是只是一个命令行窗口中闪光.


"暂停"的一个简洁特征是,如果没有终端接收"任何密钥"(例如,如果您的批处理文件是从系统服务运行的),它会检测到这一点并继续...
您可以使用"开始/运行"/然后键入"cmd/k"和批处理文件名,而不是污染所有批处理文件(并使其难以用于CLI极客).或者将HKCR\batfile\shell\open \命令默认字符串更改为'cmd/k"%1"%*'.或者制作另一个只运行'@cmd/k $*'的批处理文件,将其放在桌面上并删除其他批处理文件.PAUSE有很多替代方案.请考虑一下.
给Charlie Somerville +1,这是众所周知的每个游戏程序员的'go.bat'在90年代早期使用它.

17> paxdiablo..:

相当于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..:

字符串减法的示例datetime获取名为"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是从十六进制值0F,其中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

推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有