【发布时间】:2010-09-19 17:05:22
【问题描述】:
Windows 批处理文件有哪些鲜为人知但重要且有用的功能?
指南:
- 每个答案一个功能
- 提供功能的简短描述和示例,而不仅仅是文档链接
- 将答案限制在本机功能,即不需要其他软件,例如 Windows 资源工具包
澄清:我们在这里指的是由 cmd.exe 处理的脚本,这是 WinNT 变体的默认设置。
【问题讨论】:
标签: windows batch-file hidden-features
Windows 批处理文件有哪些鲜为人知但重要且有用的功能?
指南:
澄清:我们在这里指的是由 cmd.exe 处理的脚本,这是 WinNT 变体的默认设置。
【问题讨论】:
标签: windows batch-file hidden-features
续行:
call C:\WINDOWS\system32\ntbackup.exe ^
backup ^
/V:yes ^
/R:no ^
/RS:no ^
/HC:off ^
/M normal ^
/L:s ^
@daily.bks ^
/F daily.bkf
【讨论】:
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 /?。
PUSHD path
带你到path指定的目录。
POPD
带你回到你“推送”的目录。
【讨论】:
cd不同,您还可以使用pushd在不同驱动器上的目录之间切换。 (如果您在 C:\Windows 中并希望在 D:\Games 中,则 pushd D:\Games 会将您带到那里,而不是输入 D: 和 cd D:\Games。)
不确定这在 batch 文件中会有多大用处,但在命令提示符中使用它是一个非常方便的命令:
C:\some_directory> start .
这将在“some_directory”文件夹中打开 Windows 资源管理器。
我发现这非常节省时间。
【讨论】:
open . 会做同样的事情。
start 不仅仅是打开当前文件夹。您可以将任何文件传递给它,它将使用配置的查看器打开它。给它一个 URL,你的默认浏览器就会打开,等等......
我一直觉得每行都用关键字标记的 cmets 很难阅读:
REM blah blah blah
更容易阅读:
:: blah blah blah
【讨论】:
rem 是已记录的关键字,而 :: 只是一个实现细节。虽然:: 不太可能停止工作,但通常建议不要依赖未记录的行为。
goto : 跳转到标签。 :-) 和 goto -) 也可以。
变量子串:
> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456
【讨论】:
for %a in ...) 的局部变量结合使用,因为它们不像环境变量那样需要结束百分号;您必须首先将它们分配给环境变量(使用延迟扩展!),然后提取子字符串。
The FOR command!虽然我讨厌编写批处理文件,但我很感激。
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k
将解析 myfile.txt 中的每一行,忽略以分号开头的行,将每行的第二个和第三个标记传递给 for 正文,标记由逗号和/或空格分隔。 注意 for body 语句引用 %i 获取第二个标记,%j 获取第三个标记,以及 %k 获取第三个之后的所有剩余标记。
您还可以使用它来迭代目录、目录内容等...
【讨论】:
我没有在脚本中乱扔 REM 或 :: 行,而是在每个脚本的顶部执行以下操作:
@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\long dir name\文件夹中执行下面的脚本test.bat,
@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 ^| ^< ^> ^& ^\ ^^
【讨论】:
HEAD^) 是有问题的。
能够运行命令并处理输出(如 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
【讨论】:
type nul > filename.ext。
ren > blah.txt
隐藏命令重定向到>nul 2>&1的所有输出。
例如,某些命令行程序即使重定向到 >nul 也会显示输出。但是,如果你像下面的行那样重定向输出,所有的输出都将被抑制。
PSKILL NOTEPAD >nul 2>&1
编辑:请参阅 Ignoring the output of a command 了解其工作原理。
【讨论】:
taskkill。
PAUSE
停止执行并显示如下提示:
按任意键继续。 . .
如果您想通过在 Windows 资源管理器中双击来运行批处理并希望实际查看输出而不仅仅是命令窗口的闪烁,这很有用。
【讨论】:
echo.|batch-with-pause.bat 将具有与按“任意键”相同的效果...
相当于 bash(和其他 shell)
echo -n Hello # or
echo Hello\\c
它输出“Hello”而没有尾随换行符。执行此操作的 cmd hack:
<nul set /p any-variable-name=Hello
set /p 是一种提示用户输入的方式。它发出给定的字符串,然后等待(在同一行,即没有 CRLF),让用户输入响应。
<nul 只是将空响应通过管道传递给set /p 命令,因此最终结果是发出的提示字符串。 (由于空响应,使用的变量保持不变。)
问题是:无法输出前导等号,并且在 Vista 上会删除前导空白字符,但在 XP 上不会。
【讨论】:
设置环境变量时搜索替换:
> @set fname=%date:/=%
...从日期中删除“/”以用于带时间戳的文件名。
还有子字符串...
> @set dayofweek=%fname:~0,3%
【讨论】:
整数运算:
> SET /A result=10/3 + 1
4
【讨论】:
命令分隔符:
cls & dir
copy a b && echo Success
copy a b || echo Failure
在第 2 行,&& 之后的命令只有在第一个命令成功的情况下才会运行。
在第 3 行,|| 之后的命令仅在第一个命令失败时运行。
【讨论】:
输出一个空行:
echo.
【讨论】:
您可以链接 if 语句以获得类似短路布尔值“和”的效果。
if foo if bar baz
【讨论】:
if foo ( if bar ( baz ) )(想象括号后的换行符。)
快速将 Unicode 文本文件(16 位/字符)转换为 ASCII DOS 文件(8 位/字符)。
C:\> type unicodeencoded.txt > dosencoded.txt
作为奖励,如果可能的话,字符被正确映射。
【讨论】:
if 块结构:
if "%VS90COMNTOOLS%"=="" (
echo: Visual Studio 2008 is not installed
exit /b
)
【讨论】:
%ERRORLEVEL%;这就是if errorlevel <foo> 的用途。而 that 实际上确实在这样的块中起作用。
变量的延迟扩展(为了很好的措施,加入了子字符串):
@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
【讨论】:
不提供太多功能,但您可以将 title 命令用于多种用途,例如在任务栏中的长脚本上提供状态,或仅用于增强用户反馈。
@title Searching for ...
:: processing search
@title preparing search results
:: data processing
【讨论】:
手头没有编辑器,需要创建批处理文件?
copy con test.bat
只需键入命令,按回车换行。 按 Ctrl-Z 和 Enter 关闭文件。
【讨论】:
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”不起作用
颜色名称调用
颜色?
【讨论】:
使用空格和转义字符完全控制输出。:
echo. ^<resourceDir^>/%basedir%/resources^</resourceDir^>
【讨论】:
TheSoftwareJedi 已经提到了 for 命令,但我将再次提及它,因为它非常强大。
下面以 YYYYMMDD 格式输出当前日期,我在生成备份目录时使用它。
for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a
【讨论】: