您的代码存在以下问题:
- 在批处理文件中,
for
元变量前面必须有two %
- 与命令提示符中的符号相反(cmd
),因此改变%a
等,以%%a
, ETC。;否则会出现语法错误;
- 您可以避免过滤掉输出的标题
wmic
by findstr /V
当使用skip=1
的选项for /F
;
- 而不是财产
Name
我建议使用DeviceID
,根据这个超级用户线程:属性有什么区别Name, Caption and DeviceID(执行时wmic LogicalDisk)? https://superuser.com/q/1074840;
- 不确定您要查询哪些驱动器,但也许您只需要本地磁盘;如果是这样,请添加该子句
where "DriveType=3"
;参考微软这篇文章:Win32_LogicalDisk 类 https://learn.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-logicaldisk;
- 临时 VBScript 脚本的创建应该发生在
if
调用它的条件也是为了避免无意义的文件写入活动;
- 您在每次循环迭代中附加到文本文件,但您从未在开始时初始化空文件;也许这是故意的行为,但我不这么认为;无论如何,你可以为整个重定向一次
for /F
循环,或者(覆盖)写(>
) 或附加 (>>
), 根据你喜欢的;
- 将管道插入
type
命令是没有用的,因为type
无论如何都不接受任何传入数据;我猜是|
符号应替换为&
;尽管如此,type
命令在循环中没有意义,我认为它应该在循环之后执行,而不是一次性显示完整的收集数据;
- the
echo(
可以删除,因为它只是向控制台写入一个空行;
- 最后应清除临时 VBScript 文件;
纠正所有这些事情会产生这样的批处理脚本(为了便于阅读,我不会将其全部写在一行中):
> "C:\test\test2.txt" (
for /F "skip=1 tokens=1-3" %%a in ('
wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
') do @(
if not "%%c"=="" (
> "%TEMP%\tmp.vbs" echo WScript.Echo "%%a" ^& " free=" ^& FormatNumber^(CDbl^(%%b^) / 1024 / 1024 / 1024, 2^) ^& " GiB" ^& " size=" ^& FormatNumber^(CDbl^(%%c^) / 1024 / 1024 / 1024, 2^) ^& " GiB"
CScript //NoLogo "%TEMP%\tmp.vbs"
)
)
)
type "C:\test\test2.txt"
del "%TEMP%\tmp.vbs"
不过,整个方法还可以改进:
- 临时 VBScript 脚本可以编写一次,而不是每次编写
for /F
循环迭代;为此,您需要将变量值作为命令行参数传递;请参阅此线程以了解其工作原理:在 VBscript 中使用命令行参数 https://stackoverflow.com/q/2469754;
- using
echo
编写临时 VBScript 文件需要大量转义,例如^&
, 例如;为了避免这种情况,我们可以将 VBScript 代码放置在前缀为::::
,批处理文件解释器将其视为无效的跳转标签,甚至可以通过放置exit /B
就在他们面前;这个块可以很容易地被提取findstr
,并且冒号可以通过删除for /F
;
这就是我的意思:
> "%TEMP%\tmp.vbs" (for /F "tokens=* delims=:" %%z in ('findstr /B "::::" "%~f0"') do @echo/%%z)
> "C:\test\test2.txt" (
for /F "skip=1 tokens=1-3" %%a in ('
wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
') do @(
if not "%%c"=="" CScript //NoLogo "%TEMP%\tmp.vbs" "%%a" "%%b" "%%c"
)
)
type "C:\test\test2.txt"
del "%TEMP%\tmp.vbs"
exit /B
::::If WScript.Arguments.Count < 3 Then WScript.Quit 1
::::WScript.Echo WScript.Arguments.Item(0) & _
:::: " free=" & FormatNumber(CDbl(WScript.Arguments.Item(1)) / 1024 / 1024 / 1024, 2) & " GiB" & _
:::: " size=" & FormatNumber(CDbl(WScript.Arguments.Item(2)) / 1024 / 1024 / 1024, 2) & " GiB"
在应用本线程中演示的技术时,您甚至可以避免使用包含 VBScript 代码的临时文件:是否可以在不使用临时文件的情况下在批处理文件中嵌入并执行 VBScript? https://stackoverflow.com/q/9074476
(另请参阅以下 Microsoft 文章:使用 Windows 脚本文件 (.wsf) https://msdn.microsoft.com/en-us/library/15x4407c.aspx, and 你们为什么不使用 .WSF 文件? https://blogs.msdn.microsoft.com/gstemp/2004/02/24/how-come-you-guys-dont-use-wsf-files/.)
<!-- :Batch script section
> "C:\test\test2.txt" (
for /F "skip=1 tokens=1-3" %%a in ('
wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
') do @(
if not "%%c"=="" CScript //NoLogo "%~f0?.wsf" "%%a" "%%b" "%%c"
)
)
type "C:\test\test2.txt"
exit /B
---- WSF script section -->
<job><script language="VBScript">
If WScript.Arguments.Count < 3 Then WScript.Quit 1
WScript.Echo WScript.Arguments.Item(0) & _
" free=" & FormatNumber(CDbl(WScript.Arguments.Item(1)) / 1024 / 1024 / 1024, 2) & " GiB" & _
" size=" & FormatNumber(CDbl(WScript.Arguments.Item(2)) / 1024 / 1024 / 1024, 2) & " GiB"
</script></job>
这是另一种不使用临时 VBScript 文件的方法,应用此线程中说明的方法:HTA 和批处理混合,从 BATCH 部分传递变量 https://stackoverflow.com/q/43105028。这样做的缺点是 HTA 窗口的出现和消失会短暂闪烁。
(另请参阅这篇 Microsoft 文章:HTML 应用程序 (HTA) https://blogs.msdn.microsoft.com/noahc/2007/03/26/html-applications-htas/.)
<!-- ::Batch script section ----
> "C:\test\test2.txt" (
for /F "skip=1 tokens=1-3" %%a in ('
wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
') do @(
if not "%%c"=="" set "DeviceID=%%a" & set "FreeSpace=%%b" & set "Size=%%c" & MSHTA "%~f0"
)
)
type "C:\test\test2.txt"
exit /B
---- ::HTA script section -->
<script language="VBScript">
Set Env = CreateObject("WScript.Shell").Environment("Process")
Set StdOut = CreateObject("Scripting.FileSystemObject").GetStandardStream(1)
If Not Env("DeviceID") = "" Then
StdOut.WriteLine(Env("DeviceID") & _
" free=" & FormatNumber(CDbl(Env("FreeSpace")) / 1024 / 1024 / 1024, 2) & " GiB" & _
" size=" & FormatNumber(CDbl(Env("Size")) / 1024 / 1024 / 1024, 2) & " GiB")
End If
Set StdOut = Nothing
Set Env = Nothing
Close()
</script>