I was looking for an easy way to get the system volumes info in GB (batch) so I got this:
for /f "tokens=1-3" %a in ('WMIC LOGICALDISK GET FreeSpace^,Name^,Size ^|FINDSTR /I /V "Name"') do @echo wsh.echo "%b" ^& " free=" ^& FormatNumber^(cdbl^(%a^)/1024/1024/1024, 2^)^& " GiB"^& " size=" ^& FormatNumber^(cdbl^(%c^)/1024/1024/1024, 2^)^& " GiB" > %temp%\tmp.vbs & @if not "%c"=="" @echo(& @cscript //nologo %temp%\tmp.vbs >> c:\test\test2.txt | type C:\test\test2.txt
It works fine if I just copy and paste it to the CMD but if I run it from a .bat file it just don't do anything.
What could I be doing wrong?
PD: I can't use PowerShell, I need it in batch.
There are the following issues in your code:
for
meta-variables must be preceded by two%
-signs in contrast to one in command prompt (cmd
), hence change%a
, etc., to%%a
, etc.; otherwise, a syntax error arises;wmic
byfindstr /V
when using theskip=1
option offor /F
;Name
I recommend to useDeviceID
, according to this Super User thread: What is the difference between propertiesName
,Caption
andDeviceID
(when executingwmic LogicalDisk
)?;where "DriveType=3"
; refer to this Microsoft article: Win32_LogicalDisk class;if
condition where it is called as well in order to avoid pointless file write activities;for /F
loop, either (over-)writing (>
) or appending (>>
), as you prefer;type
command is useless, becausetype
does not accept any incoming data anyway; I guess the|
symbol should have been replaced by&
; nevertheless, thetype
command does not make sense in the loop, I think it should be executed after the loop instead to display the complete collected data once;echo(
could be removed as it just writes a blank line to the console;Correcting all these things lead to a batch script like this (I do not write it all in a single line for readability):
The whole approach could be improved though:
for /F
loop iteration; for this to work you need to pass the variable values as command line arguments; consult this thread to learn how it works: Using command line arguments in VBscript;echo
to write the temporary VBScript file requires lots of escaping, like^&
, for example; to avoid this, we could place the VBScript code in a block that is prefixed by::::
, which is seen as an invalid jump label by the batch file interpreter, and they could even be skipped by placing anexit /B
just before them; this block can easily be extracted byfindstr
, and the colons can be removed byfor /F
;So this is what I mean:
You could even avoid a temporary file holding the VBScript code when applying the technique demonstrated in this thread: Is it possible to embed and execute VBScript within a batch file without using a temporary file?
(Refer also to these Microsoft articles: Using Windows Script Files (.wsf), and How Come You Guys Don’t Use .WSF Files?.)
And here is yet another approach that does not use a temporary VBScript file, applying the method illustrated in this thread: HTA & Batch Hybrid, passing variables from BATCH section. The disadvantage of this is brief flickers of HTA windows appearing and disappearing.
(Refer also to this Microsoft article: HTML Applications (HTAs).)