Format file size of output to KB's and include thousand separator.

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
PAB
Posts: 15
Joined: 12 Aug 2019 13:57

Format file size of output to KB's and include thousand separator.

#1 Post by PAB » 12 Aug 2019 14:19

Good evening,

I have managed to put the following together which almost does as I want . . .

Code: Select all

For /f "tokens=*" %%A in ('dir /b /s /a:-d') Do echo %%~fA %%~zA >> "Master.txt"
Is there any way that I can . . .

[1] Have the output in KB's?
[2] Include the thousand separator?

Any help will be appreciated!

Thanks in advance.

penpen
Expert
Posts: 1714
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Format file size of output to KB's and include thousand separator.

#2 Post by penpen » 13 Aug 2019 19:27

Ad hoc, i would use a hybrid solution (but only works if JScript execution is enabled on your System):

Code: Select all

<!-- :main
@echo off
setlocal enableExtensions disableDelayedExpansion

For /f "tokens=*" %%A in ('dir /b /s /a:-d') Do (
	<nul set /p "=%%~fA "
	cscript //nologo "%~f0?.wsf" //job:divide "%%~zA" "1024"
	echo(KB
)


exit /b

--->
<job id="divide">
	<script language="JScript">
var dividend=WScript.Arguments(0);
var divisor=WScript.Arguments(1);
var result=dividend/divisor;

WScript.Stdout.Write(result.toLocaleString());
	</script>
</job>
penpen

PAB
Posts: 15
Joined: 12 Aug 2019 13:57

Re: Format file size of output to KB's and include thousand separator.

#3 Post by PAB » 14 Aug 2019 03:24

Thanks for the reply penpen, it is appreciated.

Unfortunately that doesn't work for me!
I was hoping for a purely batch script solution.

Thanks again.

penpen
Expert
Posts: 1714
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Format file size of output to KB's and include thousand separator.

#4 Post by penpen » 14 Aug 2019 08:00

A pure batch solution is much slower, if your files are bigger than 1 GB you should use something like that:

Code: Select all

@echo off
setlocal enableExtensions disableDelayedExpansion
For /f "tokens=*" %%A in ('dir /b /s /a:-d') Do (
	set "name=%%~A"
	call :divide "size" "%%~zA" "1024"
	setlocal enableDelayedExpansion
	set "line=!name! !size!KB"
	echo(!line!
	endlocal
)


exit /b

:divide rounded to two decimals places
:: %~1	variable name to store the result to
:: %~2	dividend
:: %~3	divisor
setlocal enableDelayedExpansion
set "dividend=%~2"
set "divisor=%~3"
set "remainder=0"
set "digit="
set "result="
set "rounded="


:: divide, three decimnal places
for /f %%a in ('cmd /u /cecho %dividend%000^| cmd /a /cfind /v ""') do (
	set /a "remainder=10 * remainder + %%~a, digit=remainder / divisor, remainder=remainder %% divisor"
	set "result=!digit! !result!"
)

:: round
set "overflow=5"
for %%a in (%result%) do (
	set /a "digit=(%%~a+overflow)%%10, overflow=(%%~a+overflow)/10"
	set "rounded=!rounded! !digit!"
)
set "rounded=!rounded:~2!"

:: add thousand seperator
set "result=.%rounded:~3,1%%rounded:~1,1%"
set "rounded=%rounded:~5%"
set "group=0"

for %%a in (%rounded%) do (
	if !group! == 3 (
		set "result=%%~a,!result!"
		set "group=1"
	) else (
		set "result=%%~a!result!"
		set /a "group+=1"
	)
)

for /f "tokens=1* delims=,0" %%a in ("x%result%") do (
	set "result=%%~b"
)
if "%result:~0,1%" == "." set "result=0!result!"

endlocal & set "%~1=%result%"
goto :eof
penpen

PAB
Posts: 15
Joined: 12 Aug 2019 13:57

Re: Format file size of output to KB's and include thousand separator.

#5 Post by PAB » 14 Aug 2019 09:00

Thanks penpen,

I would never have asked if I had thought it was going to be so complicated, sorry. I do appreciate the time you have spent on this.

I saw the output flash by [I don't know where it is stored] and it does indeed do what I was after, THANK YOU.
The thing is, I really wanted the output to go into the folder it is run from as a filename.txt file for example.

Thanks again.

siberia-man
Posts: 126
Joined: 26 Dec 2013 09:28
Contact:

Re: Format file size of output to KB's and include thousand separator.

#6 Post by siberia-man » 14 Aug 2019 12:26

Using batch scripting is limited by file size no more 2 G (in fact less than 2^31-1). The following script works in this limitation only. I guess applying some non-trivial tricks could extend usage but the script will become too complicated indeed.

Code: Select all

@echo off

setlocal

set "DIGIT_GROUPING=,"

call :fsize "%COMSPEC%"
call :fsize "%COMSPEC%" KiB
call :fsize "%COMSPEC%" KB

endlocal
goto :EOF

:: SYNOPSIS
::
:: call :fsize [/v VARNAME] FILENAME [UNIT]
::
:: DESCRIPTION
::
:: Estimate the file size and scale it by UNIT.
:: If the option /v VARNAME is specified the result will be stored to
:: the variable VARNAME instead of printing.
::
:: UNIT is an optional unit prefix to represent big numbers in the
:: human-friendly format.
:: Units are of power 1000: KB, MB, GB
:: Units are of power 1024: KiB, MiB, GiB
::
:: ENVIRONMENT
::
:: DIGIT_GROUPING a character to be used as a delimiter of thousands.
:fsize
setlocal

set "fs_var="

if /i "%~1" == "/v" (
	set "fs_var=%~2"
	shift /1
	shift /1
)

set /a "fs_KiB=1024"
set /a "fs_MiB=fs_KiB * 1024"
set /a "fs_GiB=fs_MiB * 1024"

set /a "fs_KB=1000"
set /a "fs_MB=fs_KB * 1000"
set /a "fs_GB=fs_MB * 1000"

if not "%~2" == "" (
	if not defined fs_%~2 (
		echo:Unknown unit: "%~2">&2
		exit /b 1
	)
	rem The whitespace after "=" is mandatory
	set    "fs_name= %~2"
	set /a "fs_unit=fs_%~2"
)

set /a "fs_size=%~z1"
if defined fs_unit set /a "fs_size /= fs_unit"

if not defined DIGIT_GROUPING goto :fsize_2
if %fs_size% lss 1000 goto :fsize_2

set "fs_result="
set /a "fs_dividend=fs_size"

:fsize_1
set /a "fs_remainder=fs_dividend %% 1000"
set /a "fs_dividend=fs_dividend / 1000"

set "fs_remainder=000%fs_remainder%"
set "fs_result=%fs_remainder:~-3%%DIGIT_GROUPING:~0,1%%fs_result%"

if %fs_dividend% gtr 1000 goto :fsize_1

if %fs_dividend% gtr 0 (
	set "fs_result=%fs_dividend%%DIGIT_GROUPING:~0,1%%fs_result%"
)

set "fs_size=%fs_result:~0,-1%"

:fsize_2

if not defined fs_var (
	echo:%fs_size%%fs_name%
	goto :EOF
)

endlocal && set "%fs_var%=%fs_size%%fs_name%"
goto :EOF

penpen
Expert
Posts: 1714
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Format file size of output to KB's and include thousand separator.

#7 Post by penpen » 17 Aug 2019 06:53

PAB wrote:
14 Aug 2019 09:00
The thing is, I really wanted the output to go into the folder it is run from as a filename.txt file for example.
Do you want to hardcode the name of that file and append it? In that case change the first part to:

Code: Select all

(
	For /f "tokens=*" %%A in ('dir /b /s /a:-d') Do (
		set "name=%%~A"
		call :divide "size" "%%~zA" "1024"
		setlocal enableDelayedExpansion
		set "line=!name! !size!KB"
		echo(!line!
		endlocal
	)
) >>"filename.txt"
If you want to create the resulting file new everey time you start that batch, then use ">"filename"" instead of ">>"filename"".

Else you could call that batch file and redirect its output; assumed it's name is "test.bat"; append example:

Code: Select all

:: append file
>>"filename.txt" call test.bat
penpen

PAB
Posts: 15
Joined: 12 Aug 2019 13:57

Re: Format file size of output to KB's and include thousand separator.

#8 Post by PAB » 19 Aug 2019 13:22

Brilliant, thanks very much for the replies, it is appreciated.

Post Reply