You can filter out the 'bytes free' line of DIR output using FIND
dir | find "bytes free"
You can parse that line using FOR with the /F switch and separate the 3rd space-delimited token (which is the number of bytes free) and assign it to a variable. In the FOR dataset you need to escape the pipe symbol with a caret
for /f "tokens=1-3 delims= " %%A in ('dir ^| find "bytes free"') do set bytesfree=%%C
You now have the bytes free held in the variable %bytesfree% BUT you cannot use SET /A to divide it if the bytes free amount to 2 GB or more because batch arithmetic is limited to 32 bits of precision (i.e integers between -2,147,483,647 and + 2,147,483,647)
However you can use the Visual Basic Script eval() function which is not limited in this way. You can create a simple one-line VBScript, pass the calculation to it and use FOR /F to parse the results.
Wscript.echo eval(WScript.Arguments(0))
You may find a large number of digits after the decimal point like so...
21.4063174422784
so you can use another VBScript oneliner to format the number, adding a leading zero if required (for numbers less than 1 GB) and parse the output with FOR /F again
Putting it all together....
@echo off
Set Drive=D:
for /f "tokens=1-3 delims= " %%A in ('dir %Drive% ^| find "bytes free"') do set bytesfree=%%C
echo Wscript.echo eval(WScript.Arguments(0)) > Calculate.vbs
for /f "delims=" %%A in ('cscript //nologo calculate.vbs %bytesfree%/1073742268') do set GBfreeRaw=%%A
REM How many digits after the decimal point
set decimals=2
REM If you don't want a leading zero if GB < 1 then change this to False
Set LeadingZero=True
echo Wscript.echo Formatnumber(WScript.Arguments(0), %decimals%, %LeadingZero%) > Nformat.vbs
for /f "delims=" %%A in ('cscript //nologo NFormat.vbs %GBfreeRaw%') do set GBfreeFormatted=%%A
echo %Drive% GB free: %GBfreeFormatted%
Example output
D: GB free: 128.34