Do a command on a file while condition is True - windows

for %%a in (.\*.jpg) do #if %%~za gtr 245760 (
:WhileD
resize /overwrite /width:imagewidth-100 %%a %%~na.jpg
if %%~za gtr 245760 goto WhileD
)
The Code above should check all images in a folder and if it is greater than 240KB, it resizes it till its size becomes less than 240KB, and then process to the next file,
But it is not working :(

goto commands break for loops. Use routines to contain goto sub-loops.
for %%a in (.\*.jpg) do #if %%~za gtr 245760 ( call :WhileD "%%~a" ) else echo add move command here.
exit /b 0
:WhileD <File>
resize /overwrite /width:imagewidth-100 %1 %~n1.jpg
if %~z1 gtr 245760 goto WhileD
exit /b 0
Update
Added else condition.

:WhileD
for %%a in (.\*.jpg) do if %%~za gtr 245760 (
resize /overwrite /width:imagewidth-100 %%a %%~na.jpg
goto WhileD
)
This should solve the problem.

Try this
FOR %%A IN (*.jpg) DO CALL :CHECKFILE %%A %%~nA
EXIT /B 0
:CHECKFILE
FOR /F "usebackq" %%A IN ('%1') DO SET FSIZE=%%~zA
IF %FSIZE% LEQ 245760 EXIT /B 0
resize /overwrite /width:imagewidth-100 %1 %2.jpg
GOTO CHECKFILE

Related

Batch incremental name change only updates a few files at a time

I am attempting to create a batch file that will rename a series of file based on an XML file. It works until it encounters a file name with the same name at which point it skips the file. I was able to amend the script to create an incremental version of the file, the issue that I am having now is the script will cycle through just a few files and then it exits. Any ideas why it's doing that?
for %%z in ("C:\Recordings\AT1*.WAV") do (
for /f tokens^=4^,8^,10^,12^ delims^=^" %%a in ('type "C:\Recordings\index.xml"^|find /i "%%~nxz"') do (
for /f "tokens=1,2 delims=:" %%t in ("%%b") do (
ren "%%z" "%%c-%%t-%%u_%%d%%~xz" 2>nul
if errorlevel 1 set "Number=2" & call :NumberedRename "%%z" "%%c_%%t-%%u_%%d%%~xz"
goto :EOF
)
)
)
)
:NumberedRename
if exist "%~n2_%Number%%~x2" set /A "Number+=1" & goto NumberedRename
ren %1 "%~n2_%Number%%~x2"
goto :EOF
Here is an example of the output that I am able to see at the moment:
C:\Recordings>for %z in ("C:\Recordings\AT1*.WAV") do (for /F tokens=4,8,10,12 delims=" %a in ('type "C:\Recordings\index.xml"|find /i "%~nxz"') do (for /F "tokens=1,2 delims=:" %t in ("%b") do (
ren "%z" "%c-%t-%u_%d%~xz" 2>nul
if errorlevel 1 set "Number=2" & call :NumberedRename "%z" "%c_%t-%u_%d%~xz"
goto :EOF
) ) )
C:\Recordings>(for /F tokens=4,8,10,12 delims=" %a in ('type "C:\Recordings\index.xml"|find /i "AT1_ID1_TT3_ID6-1626034093.52156.WAV"') do (for /F "tokens=1,2 delims=:" %t in ("%b") do (
ren "C:\Recordings\AT1_ID1_TT3_ID6-1626034093.52156.WAV" "%c-%t-%u_%d.WAV" 2>nul
if errorlevel 1 set "Number=2" & call :NumberedRename "C:\Recordings\AT1_ID1_TT3_ID6-1626034093.52156.WAV" "%c_%t-%u_%d.WAV"
goto :EOF
C:\Recordings>if exist "John Doe 1_2021-07-11 15-08_9394056960_2.WAV" set /A "Number+=1" & goto NumberedRename
C:\Recordings>ren "C:\Recordings\AT1_ID1_TT3_ID6-1626034093.52156.WAV" "John Doe 1_2021-07-11 15-08_9394056960_2.WAV"
) ) )
Shortly after posting the question I tinkered with the script and realized that one of the goto :EOF was causing the script to end prematurely. I removed the goto :EOF and it seems to be working as intended.
Updated Script
for %%z in ("C:\Recordings\AT1*.WAV") do (
for /f tokens^=4^,8^,10^,12^ delims^=^" %%a in ('type "C:\Recordings\index.xml"^|find /i "%%~nxz"') do (
for /f "tokens=1,2 delims=:" %%t in ("%%b") do (
ren "%%z" "%%c-%%t-%%u_%%d%%~xz" 2>nul
if errorlevel 1 set "Number=2" & call :NumberedRename "%%z" "%%c_%%t-%%u_%%d%%~xz"
)
)
)
)
:NumberedRename
if exist "%~n2_%Number%%~x2" set /A "Number+=1" & goto NumberedRename
ren %1 "%~n2_%Number%%~x2"
goto :EOF

Batch variable store result from command

It seems for me a very simple question, however I am struggling a lot with this and don't find an answer yet.
My aim is to count occurences of a specific string in a file.
I do or try to do this using following command:
for /f "tokens=2 delims=;" %%a in ('path to file with searchstring') do (
set count=('path to file I am searching in' find /c "%%a")
if !count! NEQ 0 echo !count!
)
Seems straightforward for me however the second line seems to be wrong as the script exits.
I want to save the result of findin a var because I only wants to outpout Nonzero resutls.
Here's an example batch-file using findstr, for better word matching, (It uses the filenames from your previous question):
#(For /F "UseBackQTokens=2Delims=;" %%G In ("classID.txt")Do #(Set "count=0"
For /F %%H In ('^""%__AppDir__%findstr.exe" /IN "\<%%G\>" "trc.txt"^"'
)Do #(Set /A count+=1)&SetLocal EnableDelayedExpansion
If !count! Gtr 0 (Echo %%G: !count!)&Endlocal))&Pause
Here it is fully parenthesized over multiple lines for you to better understand:
#Echo Off
For /F "UseBackQ Tokens=2 Delims=;" %%G In (
"classID.txt"
) Do (
Set "count=0"
For /F %%H In (
'^""%__AppDir__%findstr.exe" /I /N "\<%%G\>" "trc.txt"^"'
) Do (
Set /A count +=1
)
SetLocal EnableDelayedExpansion
If !count! Gtr 0 (
Echo %%G: !count!
)
Endlocal
)
Pause
And a fully parenthesized example of it outputting the results to a file named results.txt:
#Echo Off
(
For /F "UseBackQ Tokens=2 Delims=;" %%G In (
"classID.txt"
) Do (
Set "count=0"
For /F %%H In (
'^""%__AppDir__%findstr.exe" /IN "\<%%G\>" "trc.txt"^"'
) Do (
Set /A count +=1
)
SetLocal EnableDelayedExpansion
If !count! Gtr 0 (
Echo %%G: !count!
)
Endlocal
)
)>"results.txt"

how to compare numeric variables in batch files

why doesn't this work?
SET FIRST=""
SET COUNT=0
FOR %%F IN (dir *.png) DO (
IF %COUNT% NEQ 0 GOTO _skip
SET FIRST=%%F
:_skip
ECHO "%%F",
SET /A COUNT=COUNT+1
)
It sets FIRST to the last *.png because the IF condition fails, because COUNT - although is incremented by set /A, the IF %COUNT% doesn't ever work. Very frustrating.
Don't need to count, just do goto skip after echo line.
#echo off
for /f "delims=" %%f in ('dir /b *.png') do (
rem :: you can use "echo %%f" instead of "set first=%%f"
set first=%%f
goto _skip
)
:_skip
echo %first%
you mixing two things to scan folder.
Here is the second way:
#echo off
for %%f in (*.png) do (
set first=%%f
goto _skip
)
:_skip
echo %first%
exit /b 0
If you need absolutely to count, here is the way to skip with count. As stated in comment, you need to enable delayedExpansion
#echo off
set count=1
for %%f in (*.png) do (
set first=%%f
setlocal enabledelayedexpansion
if "!count!"=="1" goto _skip
endlocal
set /a count+=1
)
:_skip
echo !first!

Loop over an interval of files

I would like to define a for-loop (windows command line) that iterates over (numbered) intervals of files in a directory, say 1..100, and then 101..200, and 201..300 etc [Edit: regardless of the files names]. See following pseudo-code:
for %WORKDIR% %%f(1..100) in (*.htm) do (
REM DoSomething with %%f
)
for %WORKDIR% %%f(101..200) in (*.htm) do (
REM DoSomething with %%f
)
...etc
Q: Is there a way to define "numbered intervals" of files from command line?
// Rolf
You can place each function in a separate file:
:1to100
setlocal enabledelayedexpansion
set /a "file=1"
rem Skip 0 (skip=0 is omitted because it's illegal) and process 100.
for /f %%f in ('dir %workdir%\*.htm /b') do (
if !file! gtr 100 (exit /b) else (set /a "file+=1")
echo Do something with %%f.
)
endlocal
goto :eof
:100to200
setlocal enabledelayedexpansion
set /a "file=1"
rem Skip 100 and process 100.
for /f "skip=100" %%f in ('dir %workdir%\*.htm /b') do (
if !file! gtr 100 (exit /b) else (set /a "file+=1")
echo Do something with %%f.
)
endlocal
goto :eof

Batch File progress spinning wheel

I have been trying for days and can seem to get this to work. I found an example but it uses a (CryEcho) which will not work. I just wanted to add this to let the user know something is going on while im pinging IP addresses. I did find some code on here but it was confusing to me since im just starting to mess around with batch files for fun.
Anyway, I wanted to have something that used something like the example below but with text like (Waiting...[spinner]). Thanks!
#echo off
setlocal
set COUNT=0
set MAXCOUNT=10
set SECONDS=1
:LOOP
title "\"
call :WAIT
title "|"
call :WAIT
title "/"
call :WAIT
title "-"
if /i "%COUNT%" equ "%MAXCOUNT%" goto :EXIT
set /a count+=1
echo %COUNT%
goto :LOOP
:WAIT
ping -n %SECONDS% 127.0.0.1 > nul
ping -n %SECONDS% 127.0.0.1 > nul
goto :EOF
:EXIT
title FIN!
endlocal
AND I found this code as well:
#echo off
rem Example showing how to use CryEcho to produce a spinning wheel to show activity.
CryEcho Working ...
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
call :SpinAlive
call :DoSomeWork
cryecho \s\nFinished.
goto :eof
:DoSomeWork
ping -n 1 localhost > nul
goto :eof
:SpinAlive
if "%Spinner%" == "2" (cryecho \\\b)
if "%Spinner%" == "3" (cryecho -q "|"\b)
if "%Spinner%" == "4" (cryecho /\b set Spinner=0) else (cryecho -\b set Spinner=1)
set /A Spinner=%Spinner%+1
goto :eof
The main trick is here to move the cursor back on the same line.
This can be done with a carriage return or a backspace characters.
#echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
FOR /L %%n in (1,1,10) DO (
call :spinner
ping localhost -n 2 > nul
)
exit /b
:spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Waiting !spinChars:~%spinner%,1!!CR!"
exit /b
The <CR> character is created from the output of copy /z.
The output is done by set /p, as this omits the output of CR/LF at the end.
The !CR! is output each time to force the cursor to move back to the first column.
But as Win7 and Vista removes all whitespaces and also CR from the leading output of set /p, it's placed at the end.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CALL :BACKSPACE $BS
SET /A FULL_COUNT=75
SET /A MAX_COUNT=160
SET /A Spin_Delay=60
SET "_MSG=Process running..."
SET /A CTR=0
IF NOT [%1]==[] SET "_MSG=%~1"
IF NOT [%2]==[] SET /A FULL_COUNT=%2
IF NOT [%3]==[] SET /A SPIN_DELAY=%3
IF %FULL_COUNT% GTR %MAX_COUNT% SET /A FULL_COUNT=%MAX_COUNT%
<nul SET/P="%_MSG%*"
SET "SPINNER=³/Ä\"
FOR /L %%A IN (1,1,%FULL_COUNT%) DO (
CALL :DELAY %SPIN_DELAY%
<nul CALL SET/P="%$BS%%%SPINNER:~!CTR!,1%%"
SET /A CTR=%%A %% 4
)
<nul SET/P="%$BS%*"
ENDLOCAL & EXIT /B %CTR%
:BackSpace
setlocal
for /f %%a in ('"prompt $H&for %%b in (1) do rem"') do set "BS=%%a"
endlocal&call set %~1=%BS%&exit /b 0
:Delay msec
setlocal
set/a correct=0
set/a msecs=%1+5
if /i %msecs% leq 20 set /a correct-=2
set time1=%time: =%
set/a tsecs=%1/1000 2>nul
set/a msecs=(%msecs% %% 1000)/10
for /f "tokens=1-4 delims=:." %%a in ("%time1%") do (
set hour1=%%a&set min1=%%b&set sec1=%%c&set "mil1=%%d"
)
if /i %hour1:~0,1% equ 0 if /i "%hour1:~1%" neq "" set hour1=%hour1:~1%
if /i %min1:~0,1% equ 0 set min1=%min1:~1%
if /i %sec1:~0,1% equ 0 set sec1=%sec1:~1%
if /i %mil1:~0,1% equ 0 set mil1=%mil1:~1%
set/a sec1+=(%hour1%*3600)+(%min1%*60)
set/a msecs+=%mil1%
set/a tsecs+=(%sec1%+%msecs%/100)
set/a msecs=%msecs% %% 100
:: check for midnight crossing
if /i %tsecs% geq 86400 set /a tsecs-=86400
set/a hour2=%tsecs% / 3600
set/a min2=(%tsecs%-(%hour2%*3600)) / 60
set/a sec2=(%tsecs%-(%hour2%*3600)) %% 60
set/a err=%msecs%
if /i %msecs% neq 0 set /a msecs+=%correct%
if /i 1%msecs% lss 20 set "msecs=0%msecs%"
if /i 1%min2% lss 20 set "min2=0%min2%"
if /i 1%sec2% lss 20 set "sec2=0%sec2%"
set "time2=%hour2%:%min2%:%sec2%.%msecs%"
:wait
set timen=%time: =%
if /i %timen% geq %time2% goto :end
goto :wait
:end
for /f "tokens=2 delims=." %%a in ("%timen%") do set num=%%a
if /i %num:~0,1% equ 0 set num=%num:~1%
set/a err=(%num%-%err%)*10
endlocal&exit /b %err%

Resources