Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
PAB
- Posts: 139
- Joined: 12 Aug 2019 13:57
#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.
Last edited by
PAB on 22 May 2020 09:29, edited 1 time in total.
-
penpen
- Expert
- Posts: 2009
- Joined: 23 Jun 2013 06:15
- Location: Germany
#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: 139
- Joined: 12 Aug 2019 13:57
#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: 2009
- Joined: 23 Jun 2013 06:15
- Location: Germany
#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: 139
- Joined: 12 Aug 2019 13:57
#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: 208
- Joined: 26 Dec 2013 09:28
-
Contact:
#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: 2009
- Joined: 23 Jun 2013 06:15
- Location: Germany
#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: 139
- Joined: 12 Aug 2019 13:57
#8
Post
by PAB » 19 Aug 2019 13:22
Brilliant, thanks very much for the replies, it is appreciated.