10 MB are 100% correct 107 = 10000000 bytes. Most computer programs and users interpret 10 MB as 10 MiB which is 10 × 220 bytes = 10485760 bytes.
The comparison operator LSS
tries always converting first the two strings left and right this operator to 32-bit signed integers and on success runs an integer comparison. The value range of 32-bit signed integer is −231 to +231−1 which is −2147483648 to +2147483647.
A file size cannot be less than 0 bytes. The negative value range does not matter for that reason. The positive value range could be interesting here if any PNG file has 2 GiB or more bytes. However, the batch file below works also for PNG files with a file size ≥ 2 GiB due to a quirk of cmd.exe
on comparing integer values not fitting into the 32-bit signed integer range value as described in detail by weird results with IF.
The main mistake is running first a FOR loop searching recursively in the current directory for files of which long or short file name is matched by the wildcard pattern *.png
and does for each found file:
- Define respectively redefine the environment variable
maxbytes
with the string value 10240000
.
- Define respectively redefine the environment variable
size
with the string value %~zF
because of the loop variable is A
and not F
.
Both commands do not make sense.
The environment variable maxbytes
needs to be defined with the maximum files size string only once above the FOR loop. In fact the environment variable maxbytes
does not need to be defined at all because of its value is used only on one command line in entire batch file. It is enough to write the bytes string value directly as second operand of the IF condition.
The second command line inside the FOR loop results assigning always the same string %~F
to the environment variable size because of the loop variable is A
and not F
. However, the usage of %%~fA
would not make the code better as that would just result in having finally the file size of the last PNG assigned to the environment variable size
.
The two environment variables maxbytes
and size
are not defined by the code in the batch file if there is no PNG file found at all in the current directory and all its subdirectories. If the two environment variables are not defined outside of the batch file, the IF condition becomes if LSS (
which is clearly a serious syntax error causing an immediate exit of batch file processing as it can be seen on debugging the batch file.
The comparison operator LSS
is also wrong here. The condition is IF file size < 10240000
THEN which is the opposite of the wanted behavior for converting PNG files of file size ≥ 10 MB
to a JPEG file.
The loop variable references %%~A
and %%~dpna.jpg
are other syntax errors. The entire IF condition is outside the FOR loop. It is not possible to reference a loop variable in a command line which is not in body of a FOR loop.
Last the command EXIT at end of a batch file makes nearly never sense. It is in most cases just counterproductive, especially on developing and testing a batch by running it from within a command prompt window instead of double clicking on the batch file in Windows File Explorer.
The batch file code should be as follows:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir *.png /A-D-L /B /S 2^>nul') do if %%~zI GEQ 10485760 (
"G:\00OSz\12win10b zEnt-LTSC 1809 x64\05Apps\Multimedia\Pictures\Installed\png (PNGs)\Support\ImageMagick Win64 static at 16 bits-per-pixel component (portable)\bin\convert.exe" "%%I" -resize 12%% "%%~dpnI.jpg"
if exist "%%~dpnI.jpg" del /A "%%I"
)
endlocal
It is most likely better to evaluate the exit code of convert.ext
to found out if the conversion from PNG to JPEG was successful and delete the PNG file in this case.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir *.png /A-D-L /B /S 2^>nul') do if %%~zI GEQ 10485760 (
"G:\00OSz\12win10b zEnt-LTSC 1809 x64\05Apps\Multimedia\Pictures\Installed\png (PNGs)\Support\ImageMagick Win64 static at 16 bits-per-pixel component (portable)\bin\convert.exe" "%%I" -resize 12%% "%%~dpnI.jpg"
if not errorlevel 1 del /A "%%I"
)
endlocal
It would be possible to condense the batch code to a single command line on working with the Windows defaults for command extensions and delayed variable expansion.
@for /F "delims=" %%I in ('dir *.png /A-D-L /B /S 2^>nul') do @if %%~zI GEQ 10485760 "G:\00OSz\12win10b zEnt-LTSC 1809 x64\05Apps\Multimedia\Pictures\Installed\png (PNGs)\Support\ImageMagick Win64 static at 16 bits-per-pixel component (portable)\bin\convert.exe" "%%I" -resize 12%% "%%~dpnI.jpg" && del /A "%%I"
Single line with multiple commands using Windows batch file explains the conditional command operator &&
which executes the next command del
only on previous convert.exe
exited with value 0
indicating a successful execution without an error.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
del /?
dir /?
echo /?
endlocal /?
for /?
if /?
setlocal /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir
command line with using a separate command process started in background with %ComSpec% /c
and the command line inside '
appended as additional arguments.