Windows批处理文件的隐藏功能

232

Windows批处理文件中一些不太为人所知,但重要且有用的特性是什么?

指南:

  • 每个答案只涉及一个特性
  • 提供特性的简短描述示例,而不是只提供文档链接
  • 答案限于本地功能,即不需要其他软件,如Windows资源工具包

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

(另请参见:Windows批处理文件:.bat与.cmd有何区别?

91个回答

4
您可以使用errorlevel来检查指定的程序是否在系统上(当前目录或路径)可用,您的批处理文件将在其中运行。为了使其工作,您要测试的程序必须在运行,退出并设置退出代码时运行。在示例中,我将-?用作myExe的arg,大多数CLI程序都有类似的arg,例如-h、--help、-v等...这确保它仅运行并退出,留下或设置错误级别0。
myExe -? >nul 2>&1 
Set errCode=%errorlevel%
@if %errCode% EQU 0 (
    echo myExe -? does not return an error (exists)
) ELSE (
    echo myExe -? returns an error (does not exist)
)

是的,您可以直接测试errorlevel而不将其分配给errCode,但这样可以在测试和条件之间放置命令,并根据需要重复测试条件。


4

'删除目录'的子目录选项:

rd /s /q junk

3
< p > CHOICE 命令会提示用户选择多个选项之一(通过单个按键)。

@echo off
echo Please choose one of the following options
echo 1. Apple
echo 2. Orange
echo 3. Pizza
echo a, b, c. Something else
choice /c:123abc /m "Answer?"
set ChoiceLevel=%ErrorLevel%
echo Choice was: %ChoiceLevel%
%ChoiceLevel% 将是第n个选项被选择(在上面的示例中,b=5)。
更多详细信息请参见SS64.com上的CHOICE参考页面。

1
不确定 CHOICE 命令在 Windows XP 上是否标准。 - Duncan Smart

3
获取当前日期、月份和年份(独立于语言环境):
for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (call :set_date %%i %%j %%k %%l)
goto :end_set_date

:set_date
if ("%1:~0,1%" gtr "9") shift
for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo,^|date') do (set %%m=%1&set %%n=%2&set %%o=%3)
goto :eof

:end_set_date

echo day in 'DD' format is %dd%; month in 'MM' format is %mm%; year in 'YYYY' format is %yy%

哇,既令人印象深刻又有些凌乱。 - dwj

3

在想要在分支之间复制文件时,有一个小技巧:

C:\src\branch1\mydir\mydir2\mydir3\mydir4>xcopy %cd:branch1=branch2%\foo*
Overwrite C:\src\branch1\mydir\mydir2\mydir3\mydir4\foo.txt (Yes/No/All)? y
C:\src\branch2\mydir\mydir2\mydir3\mydir4\foo.txt

这里同时使用了%cd%环境变量和环境变量替换。


3

3

如果要从脚本内部解析 stdin,需要使用FOR和FIND命令的技巧:

for /f "tokens=*" %%g in ('find /V ""') do (
     :: do what you want with %%g
     echo %%g
)

1
通常情况下,SET /P 更适合这种情况。 - Coding With Style
1
SET /P 允许您向用户提出问题并获取输入。上述内容用于解析标准输入,当您无法控制的程序调用您的批处理文件并将一些文本传递给您时。假设我们使用“dir”作为测试的程序,“dir | set / P data = My data”将不起作用。然而,上述技巧可以成功解析传递给批处理文件的标准输入。 - Philibert Perusse
1
Philibert,在说“SET /P无法解析stdin”之前,你真的应该先测试一下(或者只是看看Anton在这里的条目)。这就是我所做的。:-/现在,“dir | set /p data=My data”不起作用,因为SET /P在cmd.exe的单独上下文中设置,一旦命令完成,上下文就会结束。实际上,SET /P确实分配了数据,但是一旦命令完成运行,它就立即消失了。测试“DIR |(SET / P T =&SET T)”以查看。由于整个批处理脚本都在同一个上下文中运行,因此它将正常工作。如果您测试了批处理,您会注意到这一点。 - Coding With Style
然而,我的原始评论仍然存在。你能否提供一个工作示例,在批处理文件中,可以对已放入T中的内容进行有用的操作?比如,根据结果进行分支或打印一些内容或设置另一个变量以供进一步使用。更重要的是,在不调用第二个批处理文件进行处理的情况下。 - Philibert Perusse
嗯,我有时会编写批处理脚本,要求用户输入,然后将输入重定向以进行自动化。有一次,我甚至让批处理脚本调用自身来将输入重定向到自身,但那有点奇特。 - Coding With Style
显示剩余2条评论

2

Forfiles非常有用,例如,可以递归删除所有两天前的文件。

forfiles /D -2 /P "C:\Temp" /S /C "cmd /c del @path"

2

使用正则表达式支持的Findstr:

findstr "^[0-9].*" c:\windows\system32\drivers\etc\hosts

2

使用pushd命令到UNC路径会创建一个临时驱动器映射(从Z开始向后查找下一个可用字母),并将您放置在该驱动器和路径中。当您使用popd或退出命令提示符时,临时映射将消失。

   C:\>pushd \\yourmom\jukebox

   Z:\>pushd \\yourmom\business

   Y:\>

此外,这不是一个批处理技巧,而是一个命令行环境提示。当您使用 pushd 和 popd 命令以及网络共享时,在命令行上工作时,使用 $+(显示 pushd 堆栈深度)和 $M(显示网络共享路径)修改提示符将非常有用。请保留 HTML 标记,但不要添加解释。
   C:\utils>prompt $+$m$p$g

   C:\utils>pushd m:

   +\\yourmom\pub M:\>pushd c:\

   ++c:\>pushd
   M:\
   C:\utils  

   ++c:\>popd

   +\\yourmom\pub M:\>popd

   C:\utils>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接