Batch script that needs ENABLEDELAYEDEXPANSION, but where and how? - batch-file

The following is part of a batch script I'm testing, but the 2nd IF-statement at the bottom just won't work. I'm confident I need ENABLEDELAYEDEXPANSION, but I just don't know where and how.
FOR /F "delims==" %%B IN ("Filename_example.m4v") DO (
FOR /F "tokens=1 delims=." %%C IN ("%%B") DO SET name=%%C
FOR /F "tokens=2 delims=." %%D IN ("%%B") DO (
IF "%%D" EQU "m4v" SET ext=mp4
IF "%%D" EQU "m3u8" SET ext=mp4
IF "%%D" EQU "wmv" SET ext=wmv
)
)
ECHO Filename: %name%.%ext%
SET /P name1=Rename file (Y/N) {Y}?
IF /I "%name1%" EQU "N" SET filename=%name%.%ext%
IF /I "%name1%" NEQ "N" (
ECHO New filename:
SET /P name2=
SET filename=%name2%.%ext%
)
ECHO %filename%

You can use delayed expansion (see npocmaka's answer) or, keeping the same behaviour
for %%B in ("Filename_example.m4v") do (
set "name=%%~nB"
set "ext=%%~xB"
if /i "%%~xB"==".m4v" set "ext=.mp4"
if /i "%%~xB"==".m3u8" set "ext=.mp4"
)
echo Filename: %name%%ext%
set /p "rename=Renamefile (Y/N) {Y}?"
if /i not "%rename%"=="N" (
set /p "filename=New filename"
) else (
set "filename=%name%%ext%
)
echo %filename%

To turn on delayed expansion, use the setlocal command.
setlocal enableDelayedExpansion
FOR /F "delims==" %%B IN ("Filename_example.m4v") DO (
FOR /F "tokens=1 delims=." %%C IN ("%%B") DO SET name=%%C
FOR /F "tokens=2 delims=." %%D IN ("%%B") DO (
IF "%%D" EQU "m4v" SET ext=mp4
IF "%%D" EQU "m3u8" SET ext=mp4
IF "%%D" EQU "wmv" SET ext=wmv
)
)
ECHO Filename: %name%.%ext%
SET /P name1=Rename file (Y/N) {Y}?
IF /I "%name1%" EQU "N" SET filename=%name%.%ext%
IF /I "%name1%" NEQ "N" (
ECHO New filename:
SET /P name2=
SET filename=!name2!.!ext!
)
ECHO %filename%
From what I see you need to use delayedExpansion only on the last SET.To use the delayed expansion you need ! instead of %

Next script shows
where (minimal use, but could be extended to whole script, see npocmaka's answer) and
how to use EnableDelayedExpansion (SETLOCAL).
See also %%~nB, %%~xB and other ~ modifiers in Command Line arguments (Parameters)
Moreover, minimizes user's input to the only set /P.
#ECHO OFF >NUL
SETLOCAL enableextensions
FOR %%B IN (
"FN_example.m4v"
"fn_example2.WMV"
"fn_example3.xyz"
) DO (
set "name=%%~nB"
set "ext=%%~xB"
IF /I "%%~xB" EQU ".m4v" SET "ext=.mp4"
IF /I "%%~xB" EQU ".m3u8" SET "ext=.mp4"
IF /I "%%~xB" EQU ".wmv" SET "ext=.wmv"
SETLOCAL enabledelayedexpansion
ECHO orig. filename: !name!!ext!
SET /P "name=Type new filename (or hit <Enter> to keep '!name!'): "
SET "filename=!name!!ext!"
IF /I "!name!" EQU "%%~nB" (
ECHO name unchanged: !filename!
) else (
ECHO new file name: !filename!
)
ENDLOCAL
echo(
)

Thanks for all your help thus far. I have a working script. I'm sure things could be more efficient, but at least it's working! :) Sorry for the Dutch-language usage, the code may still be useful:
#ECHO off
CLS
REM BatchGemist geschreven door Reino Wijnsma, 2015 (reino#degeelebosch.nl)
SET batchname=BatchGemist
SET version=1.0
TITLE %batchname% %version%
IF NOT EXIST youtube-dl.exe (
ECHO 'youtube-dl.exe' niet gevonden.
ECHO.
GOTO Help
)
IF NOT EXIST ffmpeg.exe (
ECHO 'ffmpeg.exe' niet gevonden.
ECHO.
GOTO Help
)
FOR /F %%A IN ('youtube-dl.exe --version') DO ECHO (youtube-dl %%A)
ECHO Voer "?" in voor Hulp
ECHO.
:Input
ECHO Voer npo.nl, rtlxl.nl, kijk.nl, of youtube programma-link in:
SET url=
SET /P url=
IF "%url%"=="?" GOTO Help
IF "%url%"=="U" GOTO Update
:: stop script bij geen Input (enter-toets)
IF "%url%"=="" GOTO:eof
:: spaties in Input niet toestaan
IF NOT "%url: =%"=="%url%" (
ECHO.
ECHO Spaties in programma-link niet toegestaan.
ECHO.
GOTO Input
)
:: alleen bepaalde websites als input toestaan
IF NOT "%url:http://www.npo.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.rtlxl.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.kijk.nl=%"=="%url%" GOTO Input2
IF NOT "%url:http://www.youtube.com=%"=="%url%" GOTO Input2
IF NOT "%url:https://www.youtube.com=%"=="%url%" GOTO Input2
IF NOT "%url:http://youtu.be=%"=="%url%" GOTO Input2
IF NOT "%url:https://youtu.be=%"=="%url%" GOTO Input2
ECHO.
ECHO Ongeldige programma-link.
ECHO.
GOTO Input
:Input2
ECHO.
youtube-dl.exe --no-warnings -F "%url%"
ECHO.
SET "format="
SET /P "format=Voer gewenst formaat in {best}: "
IF "%format%"=="" SET "format=best"
ECHO.
SET /P "task=Video-link achterhalen (J), of Downloaden (N) {J}? "
IF /I "%task%"=="N" GOTO :Download
:: voer youtube-dl uit en kopiëer video-link zonder eol-character naar het klembord
FOR /F %%B IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ECHO.
ECHO Video-link:
ECHO %%B
ECHO|SET /P ="%%B"|clip.exe
ECHO.
ECHO Video-link gekopi‰erd naar het klembord.
ECHO.
ECHO.
)
:: ‰ (Alt+0137, ANSI CP-1252) wordt in cmd.exe als ë (Alt+137, OEM CP-437 en CP-850) weergegeven
:: https://en.wikipedia.org/wiki/Code_page_437
:: https://en.wikipedia.org/wiki/Code_page_850
:: https://en.wikipedia.org/wiki/Windows-1252
GOTO Input
:Download
ECHO.
ECHO Doelmap: %~dp0
SET /P "remap=Wijzigen (J/N) {J}? "
IF /I "%remap%"=="N" (
SET "map=%~dp0"
) ELSE (
SET /P "map=Opslaan in: "
)
IF NOT "%map:~-1%"=="\" SET "map=%map%\"
FOR /F "delims==" %%C IN ('youtube-dl.exe --no-warnings --get-filename -f "%format%" "%url%"') DO (
SET "name=%%~nC"
IF /I "%%~xC"==".m4a" SET "ext=.m4a"
IF /I "%%~xC"==".m4v" SET "ext=.mp4"
IF /I "%%~xC"==".m3u8" SET "ext=.mp4"
IF /I "%%~xC"==".wmv" SET "ext=.wmv"
)
ECHO.
ECHO Bestandsnaam: %name%%ext%
SETLOCAL ENABLEDELAYEDEXPANSION
SET /P "rename=Wijzigen (J/N) {J}? "
IF /I "%rename%"=="N" (
SET "filename=%name%%ext%"
) ELSE (
SET /P "rename2=Nieuwe bestandsnaam: "
SET "filename=!rename2!%ext%
)
ECHO.
SET /P "part=Fragment downloaden (J/N) {N}? "
IF /I "%part%"=="J" (
SET /P "ss=Voer begintijd in (in seconden, of in uu:mm:ss[.xxx] vorm): "
SET /P "t=Voer tijdsduur in (in seconden, of in uu:mm:ss[.xxx] vorm): "
ECHO.
FOR /F %%D IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ffmpeg.exe -hide_banner -ss "!ss!" -i "%%D" -c copy -bsf:a aac_adtstoasc -t "!t!" "%map%%filename%"
)
) ELSE (
ECHO.
FOR /F %%E IN ('youtube-dl.exe --no-warnings -gf "%format%" "%url%"') DO (
ffmpeg.exe -hide_banner -i "%%E" -c copy -bsf:a aac_adtstoasc "%map%%filename%"
)
)
ENDLOCAL
ECHO.
ECHO.
GOTO Input
:Update
youtube-dl.exe -U
ECHO.
ECHO.
GOTO Input
:Help
ECHO.
ECHO H U L P
ECHO.
GOTO Input

Related

Tic Tac Toe Batch Game

I'm trying to code a tictactoe game in batch.
But I ran into several problems I can't solve.
After the third move of player 1, the game has to check if player 1 has won.
I tried to do that by making 8 variables of all possible 8 winlines. And then the game checks if any of the winlines equals to XXX or OOO.
The Problem is that the field variables (_f1, _f2, etc.) don't change to X or O. I set them at the beginning of the script by their numbers, but I dont understand why they dont change once a player put a X or O in that field/variable.
The code is very ugly and unnecessarily long. I'm aware of the for command and i can do basic loops, but I cant wrap my head around the syntax if the command gets too complicated. How can I put all the repititions in for loops?
#echo off
setlocal enabledelayedexpansion
title .:TIC TAC TOE:.
mode con: cols=40 lines=20
color 02
cls
goto :main
:check
if !_win1!==XXX (
echo END OF GAME
pause
)
if !_win2!==XXX (
echo END OF GAME
pause
)
if !_win3!==XXX (
echo END OF GAME
pause
)
if !_win4!==XXX (
echo END OF GAME
pause
)
if !_win5!==XXX (
echo END OF GAME
pause
)
if !_win6!==XXX (
echo END OF GAME
pause
)
if !_win7!==XXX (
echo END OF GAME
pause
)
if !_win8!==XXX (
echo END OF GAME
pause
)
goto :eof
:player2turn
choice /c 123456789 /n /m "!_player2!, it's your turn!"
if !errorlevel!==1 (
if !_f1!==1 (
set _f1=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==2 (
if !_f2!==2 (
set _f2=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==3 (
if !_f3!==3 (
set _f3=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==4 (
if !_f4!==4 (
set _f4=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==5 (
if !_f5!==5 (
set _f5=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==6 (
if !_f6!==6 (
set _f6=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==7 (
if !_f7!==7 (
set _f7=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==8 (
if !_f8!==8 (
set _f8=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==9 (
if !_f9!==9 (
set _f9=!_player2symbol!
goto :eof
) else (
goto :player1turn
)
)
goto :eof
:player1turn
choice /c 123456789 /n /m "!_player1!, it's your turn!"
if !errorlevel!==1 (
if !_f1!==1 (
set _f1=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==2 (
if !_f2!==2 (
set _f2=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==3 (
if !_f3!==3 (
set _f3=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==4 (
if !_f4!==4 (
set _f4=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==5 (
if !_f5!==5 (
set _f5=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==6 (
if !_f6!==6 (
set _f6=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==7 (
if !_f7!==7 (
set _f7=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==8 (
if !_f8!==8 (
set _f8=!_player1symbol!
goto :eof
) else (
goto :player1turn
)
)
if !errorlevel!==9 (
if !_f9!==9 (
set _f9=!_player1symbol!
echo !_win1!
echo !_player1symbol!
pause
goto :eof
) else (
goto :player1turn
)
)
goto :eof
::displaying the map
:map
echo.
echo.
echo.
echo !_f7! ^| !_f8! ^| !_f9!
echo ---------
echo !_f4! ^| !_f5! ^| !_f6!
echo ---------
echo !_f1! ^| !_f2! ^| !_f3!
echo.
echo.
echo.
goto :eof
::setting variables
:setvar
set _f1=1
set _f2=2
set _f3=3
set _f4=4
set _f5=5
set _f6=6
set _f7=7
set _f8=8
set _f9=9
set _win1=!_f7!!_f8!!_f9!
set /a _win2=!_f4!+!_f5!+!_f6!
set /a _win3=!_f1!+!_f2!+!_f3!
set /a _win4=!_f7!+!_f4!+!_f1!
set /a _win5=!_f8!+!_f5!+!_f2!
set /a _win6=!_f9!+!_f6!+!_f3!
set /a _win7=!_f7!+!_f5!+!_f3!
set /a _win8=!_f9!+!_f5!+!_f1!
goto :eof
::player settings
:setup
echo.
set /p _player1=Enter name for Player 1:
echo.
choice /c xo /n /m "!_player1! do you want to play as X or O?"
if !errorlevel!==1 (
set _player1symbol=X
set _player2symbol=O
) else (
set _player1symbol=O
set _player2symbol=X
)
echo.
echo.
set /p _player2=Enter name for Player 2:
echo.
cls
echo.
echo.
echo.
echo !_player1!(!_player1symbol!) vs. !_player2!(!_player2symbol!)
pause>nul
goto :eof
:main
setlocal
call :setup
cls
call :setvar
call :map
call :player1turn
cls
call :map
call :player2turn
cls
call :map
call :player1turn
cls
call :map
call :player2turn
cls
call :map
call :player1turn
call :check
endlocal
goto :eof
You should research and define your coding approach before write a single line of program. Also, you should learn the language features in order to make good use of its facilities. This applies to any programming language.
This is the way I would do it:
#echo off
setlocal EnableDelayedExpansion
rem Test for win: Horizontal rows
set "win[1]=%%pos[1]%%%%pos[2]%%%%pos[3]%%"
set "win[2]=%%pos[4]%%%%pos[5]%%%%pos[6]%%"
set "win[3]=%%pos[7]%%%%pos[8]%%%%pos[9]%%"
rem Test for win: Vertical cols
set "win[4]=%%pos[1]%%%%pos[4]%%%%pos[7]%%"
set "win[5]=%%pos[2]%%%%pos[5]%%%%pos[8]%%"
set "win[6]=%%pos[3]%%%%pos[6]%%%%pos[9]%%"
rem Test for win: Diagonals
set "win[7]=%%pos[1]%%%%pos[5]%%%%pos[9]%%"
set "win[8]=%%pos[7]%%%%pos[5]%%%%pos[3]%%"
for /L %%i in (1,1,9) do set "pos[%%i]=%%i"
set "taken=_"
cls
set /P "player[X]=Enter player 1 (X) name: "
set /P "player[O]=Enter player 2 (O) name: "
call :showBoard
set "players=XO"
for /L %%n in (1,1,9) do (
call :playerTurn !players:~0,1!
if !result! equ 1 echo You win^^^! & goto :EOF
set "players=!players:~1,1!!players:~0,1!"
)
echo Game was a draw...
goto :EOF
:playerTurn wichOne
choice /C 123456789 /N /M "!player[%1]!, it's your turn: "
set "choice=%errorlevel%"
if "!taken:%choice%=!" neq "%taken%" echo Bad position & goto playerTurn
set "taken=%taken%%choice%"
set "pos[%choice%]=%1"
call :showBoard
rem Test if win
set "result=0"
for /L %%i in (1,1,8) do if !result! equ 0 (
call set "line=!win[%%i]!
if "!line!" equ "%1%1%1" set "result=1"
)
exit /B
:showBoard
echo/
echo/
echo %pos[1]% ^| %pos[2]% ^| %pos[3]%
echo ---------
echo %pos[4]% ^| %pos[5]% ^| %pos[6]%
echo ---------
echo %pos[7]% ^| %pos[8]% ^| %pos[9]%
echo/
echo/
exit /B
EDIT 2021/12/08: New version added
The original version of this program was simple enough to be understand by the OP. The next version below was written with the purpose of be as efficient and short as possible:
#echo off
setlocal EnableDelayedExpansion
set "win=" & set "out="
for %%a in (1:2:3 4:5:6 7:8:9 1:4:7 2:5:8 3:6:9 1:5:9 3:5:7) do (
for /F "tokens=1-3 delims=:" %%x in ("%%a") do (
set "win=!win! ^!pos[%%x]^!^!pos[%%y]^!^!pos[%%z]^!"
if "!out:~-3,1!" neq "9" set "out=!out!$^!pos[%%x]^! ^^| ^!pos[%%y]^! ^^| ^!pos[%%z]^!"
)
)
set "out=!out:~1!"
:menu
cls
set /P "player[X]=Enter player 1 (X) name: "
set /P "player[O]=Enter player 2 (O) name: "
for /L %%i in (1,1,9) do set "pos[%%i]=%%i"
set "options=123456789" & set "filler=asdfghjkl"
for %%n in (X O X O X O X O X) do (
cls
echo/& echo/& echo %out:$=& echo --+---+--& echo %& echo/& echo/
choice /C !options! /N /M "!player[%%n]!, it's your turn: "
for /F "tokens=1,2" %%e in ("!errorlevel! !filler:~0,1!") do (
set "options=!options:%%e=%%f!" & set "filler=!filler:~1!" & set "pos[%%e]=%%n"
)
set "line=%win%"
if "!line:%%n%%n%%n=!" neq "!line!" echo You win^^^! & goto nextGame
)
echo Game was a draw...
:nextGame
echo/
pause
goto :menu
#Aacini posted a great answer, so I decided to post my own as well. As they say, there are many ways to skin a cat.
#echo off & Title Tic-Tac-Toe
setlocal enabledelayedexpansion & mode con: cols=40 lines=20 & color 02
for /F %%i in ('echo prompt $E ^| cmd') do set "n=%%iE"
:menu
cls & set gone=. & for %%p in (player[X] player[O]) do set /p "%%~p=enter name %%p: "
for /l %%i in (1,1,9) do set a%%i=%%i
for /L %%i in (1,1,4) do for %%a in (X O) do (
for %%x in (!a1!!a2!!a3! !a4!!a5!!a6! !a7!!a8!!a9! !a1!!a4!!a7! !a2!!a5!!a8! !a3!!a6!!a9! !a1!!a5!!a9! !a3!!a5!!a7!) do (
if "%%x" == "!_h!!_h!!_h!" echo !pl! wins & timeout /t 4 /NOBREAK >nul & goto :menu
)
set "pl=!player[%%a]!" & set _h=%%a
call :play
set "a!ch!=%%a"
if %%i geq 4 echo No winners & timeout /t 4 /NOBREAK >nul & goto :menu
)
:play
cls & echo(
echo !a1! ^| !a2! ^| !a3!%n% ----------%n% !a4! ^| !a5! ^| !a6!%n% ----------%n% !a7! ^| !a8! ^| !a9!%n%
choice /c 123456789 /m "!pl!'s turn"
set ch=!errorlevel!
if !ch! equ 0 exit /b
if "!gone:%ch%=!" neq "%gone%" echo That spot has been taken, try again & timeout /t 3 /NOBREAK >nul & goto :play
set "gone=%gone%!ch!"
goto :eof
And a version for older windows that does not support VT100:
#echo off & Title Tic-Tac-Toe
setlocal enabledelayedexpansion & mode con: cols=40 lines=20 & color 02
:menu
cls & set gone=. & for %%p in (player[X] player[O]) do set /p "%%~p=enter name %%p: "
for /l %%i in (1,1,9) do set a%%i=%%i
for /L %%i in (1,1,4) do for %%a in (X O) do (
for %%x in (!a1!!a2!!a3! !a4!!a5!!a6! !a7!!a8!!a9! !a1!!a4!!a7! !a2!!a5!!a8! !a3!!a6!!a9! !a1!!a5!!a9! !a3!!a5!!a7!) do (
if "%%x" == "!_h!!_h!!_h!" echo !pl! wins & timeout /t 4 /NOBREAK >nul & goto :menu
)
set "pl=!player[%%a]!" & set _h=%%a
call :play
set "a!ch!=%%a"
if %%i geq 4 echo No winners & timeout /t 4 /NOBREAK >nul & goto :menu
)
:play
cls & echo(
echo !a1! ^| !a2! ^| !a3!&echo ----------&echo !a4! ^| !a5! ^| !a6!&echo ----------&echo !a7! ^| !a8! ^| !a9!&echo(
choice /c 123456789 /m "!pl!'s turn"
set ch=!errorlevel!
if !ch! equ 0 exit /b
if "!gone:%ch%=!" neq "%gone%" echo That spot has been taken, try again & timeout /t 3 /NOBREAK >nul & goto :play
set "gone=%gone%!ch!"
goto :eof
I got the solution
All i had to do was to set the win variables later, when checking the winlines.
For the task of testing, string substitution can be used with variables to test a list of winning cell combinations concisely.
#Echo off & CHCP 65001 > nul
Set LF=^
%= Above empty line required =%
For /l %%i in (1 1 9)Do Set c%%i=_
Set Screen=Player: !Player!!LF!!LF! [!c7!][!c8!][!c9!]!LF! [!c4!][!c5!][!c6!]!LF! [!c1!][!c2!][!c3!]!LF!
Set state=!c1!!c2!!c3!,!c1!!c4!!c7!,!c1!!c5!!c9!,!c4!!c5!!c6!,!c7!!c8!!c9!,!c7!!c5!!c3!,!c3!!c6!!c9!,!c2!!c5!!c8!
Set "p1=X" & Set "p2=O"
Set /A "choices=123456789","Move=0","p%p1%%p1%%p1%=1","p%p2%%p2%%p2%=2"
Setlocal EnableDelayedExpansion & For /l %%m in (1 1 9)Do (
Set /A "player=((%%m-1) %% 2)+1"
cls & Echo(%Screen%
For /f "Delims=" %%e in ('Choice /n /c:!choices!')Do (
Set "choices=!choices:%%e=!"
For %%i in (!player!)Do Set "c%%e=!p%%i!"
)
cls & Echo(%Screen%
If %%m GTR 4 (
Set "test=%State%"
For %%i in (!p1!!p1!!p1! !p2!!p2!!p2!)Do if not "!test:%%i=!"=="!test!" (
Echo(player !p%%i! won
Goto:Eof
) ) )
Echo(draw & Endlocal

Echo output for each value in given list in bat file

With below code I'm struggling to print calculation for each value in a given list. Currently it prints total combined time for both users, I want to echo individual time for each user which is listed in 2nd row of this code.\
Any help will be appreciated.
#Echo off
For %%U in (a3rgcw shukla) Do (
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
Set "TotalSecs=0"
For %%F in ("*%U%*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Echo TotalDuration for %%U:%TotalDur%
)
Echo:
PopD
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
::Echo Session from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%
Goto :Eof
Current output:
TotalDuration for a3rgcw: 7:15:00
TotalDuration for shukla: 7:15:00
Desired output:
TotalDuration for a3rgcw: 5:15:00
TotalDuration for shukla: 2:00:00
Sample file named shukladfdf for 2nd user:
sdsdf system log created on ghg Thursday, 9 August 2018, 20:30:45 on India
Standard Time
dfg
drdwewed
end of session as 9 August 2018, 22:30:45 on India Standard Time
#Echo off
Setlocal
PushD "H:\Syslogs\" ||(Echo couldn't find dir & Pause & Exit /B 1)
For %%U in (a3rgcw shukla) Do (
Set "TotalDur="
Set "TotalSecs=0"
For %%F in ("*%%U*.txt") Do For /F "delims=" %%A in ('
findstr /I "system.log.created End.of.session" "%%F"
') Do (
Set "FileName=%%F"
Set "Flag="
Echo=%%A|findstr /I "system.log.created" 2>&1>Nul && Set "Flag=Start"
if defined Flag (
FOR /F "tokens=11" %%T in ("%%A") Do Call :TimeToSecs Start "%%T"
) Else (
FOR /F "tokens=8" %%T in ("%%A") Do Call :TimeToSecs Stop "%%T"
)
)
Set "UsrName=%%U: "
Call :Print UsrName
)
Echo:
PopD
Goto :Eof
:Print
If /i "%~1" == "UsrName" (
Echo TotalDuration for %UsrName:~,10% %TotalDur%
) else If /i "%~1" == "FileName" (
Echo Session (%FileName%^) from %Start_HMS% to %Stop_HMS% Duration:%Dur% TotalDuration:%TotalDur%
)
Goto :Eof
:TimeToSecs
Set "%1_HMS=%~2"
Echo:%~2|Findstr "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" 2>&1>Nul || (Echo wrong format %2&Goto :Eof)
For /F "tokens=1-3 delims=:" %%H in ("%~2"
) Do Set /A "%1=(1%%H-100)*60*60+(1%%I-100)*60+(1%%J-100)"
If %1 neq Stop Goto :Eof
Set /A "Diff=Stop-Start,TotalSecs+=Diff"
Call :Secs2HMS Dur %Diff%
Call :Secs2HMS TotalDur %TotalSecs%
Call :Print FileName
Goto :Eof
:Secs2HMS var value
setlocal
set /a "HH=%2/3600,mm=(%2-HH*3600)/60+100,ss=%2 %% 60+100"
Set "HHmmss= %HH%:%mm:~-2%:%ss:~-2%"
endlocal&set "%1=%HHmmss:~-10%"
Goto :Eof
Changed %U% to %%U.
Changed Echo TotalDuration for %%U:%TotalDur% to
Call Echo TotalDuration for %%U:%%TotalDur%% which
delays expansion until time of execution, instead of
parse time.
Added missing double quote with 2nd last line to close.
Added Setlocal to top of script as perhaps a 2nd run
of the script in the same CMD session could set
predined variables with values.
Added label :Print to echo the output to avoid
use of delayed expansion.

For Loop Ends Batch File Execution

My batch file is silently ending execution on the first loop (for /d "delims= eol=|" %%d in (*.*) do () and I can't tell why.
I'm not calling any other batch files
My subfolder names DO contain spaces, which I tried to handle with "delims= eol=|"
I never see !parent!!folder! echoed and it doesn't pause at the end. What am I doing wrong?
#Echo off
setlocal enabledelayedexpansion
pushd "%~dp0"
set "parent=%~dp0"
echo !parent!
set "destination=\\(test destination folder)\"
rem SET "destination=\\(prod destination folder)\"
set "FileCount=0"
for /d "delims= eol=|" %%d in (*.*) do (
set "folder=%%d"
echo !parent!!folder!
pause
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 1"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
(
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 2"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
)
)
for /d %%d in (*.*) do (
set "folder=%%d"
if not %%d==Archive (
if not %%d==Hold (
dir /b "!folder!"|find /v "">nul && ECHO "!folder! NOT EMPTY"||rmdir "!parent!!folder!"
)
)
)
pause
popd
I've took a guess at what you were doing, trying not to change the structure too much!
You'll need to add your destinations on lines 4 and 5 and your file patterns to lines 8 and 9 as necessary. (Please make sure you do not end your destination paths with back slashes):
#Echo Off
CD /D "%~dp0" 2>Nul || Exit /B
Set "Destination=\\(test destination folder)"
Rem Set "Destination=\\(prod destination folder)"
If Not Exist "%destination%\" Exit /B
Set "Pattern1=(file identifying-pattern)"
Set "Pattern2=(file identifying-pattern)"
Set /A Type1Count=Type2Count=0
SetLocal EnableDelayedExpansion
For /D %%A In (*) Do (
For %%B In ("%%A\%Pattern1%*.dat") Do (
Echo "File Type 1"
Set /A Type1Count +=1
If !Type1Count! Lss 200 (
Echo !Type1Count!. "%CD%\%%A\%%B" --^> "%Destination%\%%B"
If Not Exist "%Destination%\%%B\" MD "%Destination%\%%B"
Move /Y "%%B" "%Destination%\%%B">Nul
)
)
For %%C In ("%%A\%Pattern2%*.dat") Do (
Echo "File Type 2"
Set /A Type2Count +=1
If !Type2Count! Lss 200 (
Echo !Type2Count!. "%CD%\%%B\%%C" --^> "%Destination%\%%C"
If Not Exist "%Destination%\%%C\" MD "%Destination%\%%C"
Move /Y "%%C" "%Destination%\%%C">Nul
)
)
If /I Not "%%A"=="Archive" (
If /I Not "%%A"=="Hold" (
Set "file="
For %%D In (*) Do Set "file=1"
If Defined file (Echo %%A NOT EMPTY) Else RD "%%A" 2>Nul
)
)
)
Pause
If you're happy with it in your test you can Remark line 4 and unRemark line 5.

Batch : Multiple for /f commands

I'm trying to do "game" for my friend but when i try to load from save file it will do half of it's job
Code
set penize=0
set penizesekunda=0
for /f "EOL=: tokens=* Delims=0" %%a in (penize.txt) do (
set penize=%%a
)
for /f "EOL=: tokens=* Delims=1" %%b in (penize.txt) do (
set penizesekunda=%%b
)
echo Penize %penize% penize za sekundu %penizesekunda%
sorry it in my language (penize = money, penizesekunda = money per second)
And input is 200 200 but it should be 500 200.
If you want full code :
#echo off
title Hra (Imui)
color 6a
echo Ahoj %computername% cas %time% datum %date%
echo.
echo.
echo Vitej ve hre
echo.
echo.
echo.
echo Tvym cilem bude ovladnout cely VESMIR
echo.
timeout>nul /t 3 /nobreak
echo Nacitani!
set penize=0
set penizesekunda=0
for /f "EOL=: tokens=* Delims=0" %%a in (penize.txt) do (
set penize=%%a
)
for /f "EOL=: tokens=* Delims=1" %%b in (penize.txt) do (
set penizesekunda=%%b
)
if errorlevel 1 do (
echo Pozor nebyla nalezena zadna ulozena hra nebo doslo k chybe startovani! (hry se nachazeji v souboru penize.txt)
timeout>nul /t 3 /nobreak
cls
goto Start
)
:Start
cls
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMV
if NOT %Password%== Imui goto FAIL
if %Password%== Imui goto HesloSpravne
goto Start
:Fail
cls
echo Spatne heslo!
echo Zadej heslo prosim (zbyvaji 2 pokusy)
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMVCzech
if NOT %Password%== Imui goto FailTwo
if %Password%== Imui goto HesloSpravne
goto Fail
:FailDva
cls
echo Spatne heslo!
color ac
echo Pozor! Mas uz jenom jeden pokus!
echo Prosim zadej heslo!
set /p "Password=Zadej heslo > "
if %Password%== Admin goto RMV
if NOT %Password%== Imui goto RMV
if %Password%== Imui goto HesloSpravne
goto FailTwo
:RMV
echo Smazavam ti tvoji hru
#ECHO ON
del "Hra.exe" /P /Q /F
echo Smazavani dokonceno!
Pause>nul
exit
:HesloSpravne
cls
echo Heslo bylo spravne
goto HlavniMenu
:HlavniMenu
echo Vitej
echo %penizesekunda% %penize%
Pause>nul
Content of penize.txt :
500
200
Another (more efficient) option is to use SET /P to read each line:
<penize.txt (
set "penize="
set /p "penize="
set "penizesekunda="
set /p "penizesekunda="
)
The simple SET statements that clear each variable are there just in case the line happens to be empty or missing in the file, in which case SET /P would preserve any pre-existing variable value.
The code can be shortened by using a FOR loop, especially if you have many more lines to read:
<penize.txt ( for %%V in (penize penizesekunda) do (
set "%%V="
set /p "%%V="
))
Note that you can list the variables on separate lines, which can help readability:
<penize.txt (
for %%V in (
penize
penizesekunda
) do (
set "%%V="
set /p "%%V="
)
)
Here is some example code for you:
REM Get first line of a file
set /p penize=<penize.txt
REM Get second line of a file
for /f "skip=1" %%a in (penize.txt) do set penizesekunda=%%a

Editing an external batch config value with batch

I have a config file named config.conf with the content of:
[Config]
password=1234
usertries=0
allowterminate=0
I want to just edit the usertries value to 5, are there any batch script code that can help me do that
Thanks
This gets a little messy, but should work:
#echo off
set ConfigFile=config.conf
setlocal enabledelayedexpansion
(for /f "delims=" %%L in (%ConfigFile%) do (
set "LINE=%%L"
if "!LINE:~0,10!"=="usertries=" (echo usertries=5) else (echo !LINE!)
)) > %ConfigFile%.new
move /y %ConfigFile%.new %ConfigFile% > nul
Basically we're writing each line to a new file, unless it starts with usertries=. In which case we just insert our replacement line. Afterwards we move the new file on top of the old one to replace it.
#ECHO OFF
setlocal
::
:: set %1 to value %2 in config.conf
::
SET target=%2&IF NOT DEFINED target ECHO syntax is %0 keyname newvalue&GOTO :EOF
SET target=Config.conf
MOVE /y %target% %target%.old >NUL
FOR /f "tokens=1*delims==" %%i IN (%target%.old) DO (
IF /i %%i==%1 (ECHO %%i=%2) ELSE (
IF "%%j"=="" (ECHO %%i) ELSE (ECHO %%i=%%j)
)
) >>%target%
With this version, you can change an existing key to a value using
thisbatchname existingkey newvalue
I know I'm a little late to the party, but I decided to write a general purpose ini file utility batch script to address this question.
The script will let you retrieve or modify values in an ini-style file. Its searches are case-insensitive, and it preserves blank lines in the ini file. In essence, it allows you to interact with an ini file as a sort of very rudimentary database.
:: --------------------
:: ini.bat
:: ini.bat /? for usage
:: --------------------
#echo off
setlocal enabledelayedexpansion
goto begin
:usage
echo Usage: %~nx0 /i item [/v value] [/s section] inifile
echo;
echo Take the following ini file for example:
echo;
echo [Config]
echo password=1234
echo usertries=0
echo allowterminate=0
echo;
echo To read the "password" value:
echo %~nx0 /s Config /i password inifile
echo;
echo To change the "usertries" value to 5:
echo %~nx0 /s Config /i usertries /v 5 inifile
echo;
echo In the above examples, "/s Config" is optional, but will allow the selection of
echo a specific item where the ini file contains similar items in multiple sections.
goto :EOF
:begin
if "%~1"=="" goto usage
for %%I in (item value section found) do set %%I=
for %%I in (%*) do (
if defined next (
if !next!==/i set item=%%I
if !next!==/v set value=%%I
if !next!==/s set section=%%I
set next=
) else (
for %%x in (/i /v /s) do if "%%~I"=="%%x" set "next=%%~I"
if not defined next (
set "arg=%%~I"
if "!arg:~0,1!"=="/" (
1>&2 echo Error: Unrecognized option "%%~I"
1>&2 echo;
1>&2 call :usage
exit /b 1
) else set "inifile=%%~I"
)
)
)
for %%I in (item inifile) do if not defined %%I goto usage
if not exist "%inifile%" (
1>&2 echo Error: %inifile% not found.
exit /b 1
)
if not defined section (
if not defined value (
for /f "usebackq tokens=2 delims==" %%I in (`findstr /i "^%item%\=" "%inifile%"`) do (
echo(%%I
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
) || 1>>"%inifile%.1" echo(!line!
)
)
) else (
for /f "usebackq delims=" %%I in (`findstr /n "^" "%inifile%"`) do (
set "line=%%I" && set "line=!line:*:=!"
if defined found (
if defined value (
echo(!line! | findstr /i "^%item%\=" >NUL && (
1>>"%inifile%.1" echo(%item%=%value%
echo(%value%
set found=
) || 1>>"%inifile%.1" echo(!line!
) else echo(!line! | findstr /i "^%item%\=" >NUL && (
for /f "tokens=2 delims==" %%x in ("!line!") do (
echo(%%x
exit /b 0
)
)
) else (
if defined value (1>>"%inifile%.1" echo(!line!)
echo(!line! | find /i "[%section%]" >NUL && set found=1
)
)
)
if exist "%inifile%.1" move /y "%inifile%.1" "%inifile%">NUL
Example:
C:\Users\me\Desktop>type config.conf
[Config]
password=1234
usertries=0
allowterminate=0
[Other]
password=foo
C:\Users\me\Desktop>ini /i usertries /v 5 config.conf
5
C:\Users\me\Desktop>ini /i usertries config.conf
5
C:\Users\me\Desktop>ini /s config /i password /v bar config.conf
bar
C:\Users\me\Desktop>ini /s other /i password /v baz config.conf
baz
C:\Users\me\Desktop>type config.conf
[Config]
password=bar
usertries=5
allowterminate=0
[Other]
password=baz

Resources