IF Input filename exists in Output folder, skip BUT ALSO SKIP in FOR Statement - if-statement

Here is an excerpt of a long ffmpeg script I have and I have it:
Creating a text file of the video files in the current directory
With a FOR statement searching through the text file
Outputting to a subdir
What I want to add in is to not only not "process" go through the rest of the script if the file already exists but also not to process that ALREADY existing file. (In other words: If a copy of the file already exists in an output directory skip processing the file, but also to skip processing the duplicate file itself that was identified.)
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="
::******** DON'T EDIT-----Keeping Original Audio**************END END***************
SETlocal EnableExtensions DisableDelayedExpansion
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
::ECHO ==!TIME!================Next File: %%I ========================
SET "output=%drive%%%~pI%%~nxI" & SET "filename=%%~nxI" & SET /A FilesFound+=1
SETlocal EnableExtensions EnableDelayedExpansion
IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE IF !output2! == 1 (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
rem ===============================
rem FFProbe.exe evaluation of %%I files
rem ===============================
rem below still under the FOR statement above: for /F "delims=" %%I in (%TempFilePath%) do (
rem ------------------------------------------------------------
rem -----------------------------
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
rem ECHO This is OUTPUT-DIR "%~dp0output\"
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
ENDLOCAL
......
ENDLOCAL
ENDLOCAL
ENDLOCAL
```
I want filtration to all occur here, before it goes through the FFProbe.exe processing to speed it up. I assume in the 1st IF statement there is something I can do, but when there are multiple files, or even just 2 + 1 sub-folder, it can not carry-over the right variable i.e.
this will skip file1, process file 2, and then try to process file3
EDIT: Here is the Full Code. You will need to input what you want the destination drive to be (i.e. C: or D: etc...). It will look for mkv's and mp4's that have eac3,flac,dts,pcm,aac,or ac3 to convert to aac. ( Batch Convert Videos audio from one format to another )
#ECHO OFF
SETlocal
SET drive="~dp0"
SET string=%CD%
SETlocal EnableExtensions EnableDelayedExpansion
SET "drive=G:"
SET ^"Exclude-AlltheseFolders=#snapshot^"
SET "Convert_Audio1=Y"
SET "Convert_TO=aac"
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"
IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
IF !KeepExtraAudio_NoOrig! == Y (
SET "FFmpgXtraStream=-c:a copy"
)
IF !KeepOrigAudio! == Y (
SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
) ELSE (
SET "ConvertCodecs=1"
SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="
SETlocal EnableExtensions DisableDelayedExpansion
SET "ProgramFolder=C:\Program Files\FFmpeg-v2020\bin"
SET "ProbeOptions=-v quiet -select_streams a:0 -show_entries "stream^^=codec_name" -of json"
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
SET "output=%drive%%%~pI%%~nxI" & SET folder=%drive%%%~pI & SET "filename=%%~nxI" & SET /A FilesFound+=1
SETlocal EnableExtensions EnableDelayedExpansion
IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE IF !output2! == 1 (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
IF "!Convert_Audio1!" == "Y" (
SET "AudioCodec=" & SET "ConvertCodecs="
for /F "eol={ tokens=1,2 delims=,:[ ]{} " %%B in ('""%ProgramFolder%\ffprobe.exe" %ProbeOptions% "%%I""') do (
IF "%%~B" == "codec_name" (
IF not defined AudioCodec (
SET "AudioCodec=%%~C"
)
IF "%%~C" == "%Codec1%" (SET "ConvertCodecs=1"
) else IF "%%~C" == "%Codec2%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec3%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec4%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec5%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec6%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
)
)
)
)
IF !ConvertCodecs! == 1 (
ECHO [91m==!TIME!================[0m!Codec1! [94min[0m- %%I [91m=========[0m
)
IF "%~dp0output\!filename!" == "%%I" (set "ConvertCodecs=0")
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
SET /A count+=1
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
SET "FINALCOMMAND=ffmpeg !OverWrite!-hide_banner%FFmpgextractTime% -loglevel quiet -hwaccel auto -stats -i "%%I" -map 0:v -map_metadata 0 -movflags use_metadata_tags -map 0:a? -map 0:s:0? -c:s:0 copy -c:v copy %FFmpgXtraStream% %FFmpgConvertStream1% %KeepOrigAudio_ffMpg% "!output!" "
ECHO this is the command1: !FINALCOMMAND!
!FINALCOMMAND!
ECHO [91m=====[0mCOMPLETE[91m===============[0m .
IF not %FilesEncoded% == 0 ECHO This one was a failure. Count Encoded so far: "%FilesEncoded%"
IF not errorlevel 1 SET /A FilesEncoded+=1
powershell "$target = gi '!output!'; $source = gi '%%I'; 'CreationTime', 'LastWriteTime', 'LastAccessTime' | foreach { $target.$_ = $source.$_ }"
for /F "delims=" %%p in ("!ConvertCodecs!") do (
ECHO THIS IS P: %%p
ENDLOCAL
SET /A FilesEncoded=%%p+FilesEncoded
)
) ELSE ( ECHO ##NOT PROCESSING##: !TIME! - %%I ## & ECHO [91m=====--[0mFILE ALREADY EXISTS! [91m======================[0m Next File [91m===========================[0m )
)
)
IF %FilesFound% == 1 ( SET "PluralS=" ) else SET "PluralS=s"
ECHO [91m***************************************************************************************[0m
ECHO Re-encoded %FilesEncoded% of %FilesFound% video file%PluralS%.
ECHO [91m***************************************************************************************[0m
endlocal
endlocal
endlocal
exit /b

I think I found the answer (which I already had built-in).
In the the settings sections I designed, on the top of the full code, Under the 2nd SetLocal, SET ^"Exclude-AlltheseFolders=#snapshot^" variable, I adjusted to SET ^"Exclude-AlltheseFolders=#snapshot,output^"
This is then used to set the Exclude-Final variable:
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
Which is then used here:
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
So now as a summary I have it now excluding any folder/files "output*filename*" which I have setup as a possible output if files exist in the folder being processed from, which is next farther down the code, where it checks if file exists in current directory then create output*filename* instead.
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
SET /A count+=1
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
Excerpt of full settings code with Comments:
SETlocal EnableExtensions EnableDelayedExpansion
:: #echo on
::#######0-OVERRIDE Root Directory but keep LOGGING the SAME #############
SET "drive=G:"
::#######1-Exclude Specific Sub-Directories? #############
SET ^"Exclude-AlltheseFolders=#snapshot,output^"
:: #rem SET ^"Exclude-AlltheseFolders=#snapshot,Archive,Archive02.01,Archive2021.01.22,Video,Video2,aVideo,^!.Blu-Ray^ Final^"
::#######2-Convert Audio Track? #############
SET "Convert_Audio1=Y"
rem Rev V2.6.8.5 ADD Convert 1st group to AC3 (channel5.1 + above?), then convert 2nd group to aac (2-channel for commentary??)
SET "Convert_TO=aac"
:: rem ac3 or aac
::#######3-Codecs Desired to Convert #############
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
:: rem pcm_s24le , null , vorbis
::#######4-Keep orig Audio Track? #############
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
::#######4-Keep orig Audio Track? #############
:: MODIFY
:: Extract Time AND what to Extract (as a sample test)
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
rem SET "time_to_start_from=00:00:10" &SET "duration_to_capture=03:00:00"
::
::
::
::#######END OF SETTINGS###############################################
::*********************************************************************
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"
::#######END OF SETTINGS################################################################################################################################################################################################################
::**************************************************************************************************************************************************************************************************************************************
::#######END OF SETTINGS################################################################################################################################################################################################################
::******** DON'T EDIT-----Keeping Original Audio ***************************************************************************************************************************************************************************************
IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
IF !KeepExtraAudio_NoOrig! == Y (
SET "FFmpgXtraStream=-c:a copy"
)
IF !KeepOrigAudio! == Y (
SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
) ELSE (
SET "ConvertCodecs=1"
SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
:: ECHO This is the date and time: %DT%--%HH%.%SS%
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"

Related

Needing advice on structuring a larger scale batch file game [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 months ago.
Improve this question
So I've started getting familiar with Batch for the last year off and on, all self taught, and I've made a few little dinky projects here and there but I'm wanting to find out the best way to go about expanding my code. Using other programs for inspiration I've learned just the tip of the icebergs for "FOR loops" and using functions and small macro processes. I want to know if there is anything I should do differently in terms of architecture and planning so I can one day make amazing Batch programs like T3RROR (little weird but I'm a big fan and your my batch idol).
Below is my most complex batch code I've written and a template for future games, please add any tip or advice.
#echo off
SETLOCAL EnableDelayedExpansion
title crafting micro
color 2
:://///////////////////////////////////////////////////////////////////////
:pre_start
::initializes at the start of the program
set /a display_message=0
set /a inv_fiber=1
set /a fiber_qty=100
set /a inv_rope=0
set /a rope_qty=0
set /a inv_stick=1
set /a stick_qty=100
set /a inv_stone=1
set /a stone_qty=100
set /a inv_sharpened_stone=0
set /a sharpened_stone_qty=0
set /a inv_spear=0
set /a spear_qty=0
set /a inv_handaxe=0
set /a handaxe_qty=0
set /a inv_hammer=0
set /a hammer_qty=0
:://///////////////////////////////////////////////////////////////////////
:start
cls
echo ----------------------------------------------------
echo Crafting Menu
echo ----------------------------------------------------
echo.
echo Raw materials
echo -------------
if %inv_fiber%==1 echo Fiber: x%fiber_qty%
if %inv_stick%==1 echo Stick: x%stick_qty%
if %inv_stone%==1 echo Stone: x%stone_qty%
echo.
echo Refined Materials
echo -----------------
if %inv_rope%==1 echo Rope: x%rope_qty%
if %inv_sharpened_stone%==1 echo Sharpened Stone: x%sharpened_stone_qty%
echo.
echo Tools
echo -----
if %inv_spear%==1 echo Spear: x%spear_qty%
if %inv_handaxe%==1 echo Handaxe: x%handaxe_qty%
if %inv_hammer%==1 echo Hammer: x%hammer_qty%
::sets visibility
echo.
echo ----------------------------------------------------
echo.
echo What do you wanna craft?
echo 1. Rope (x3 Fiber)
echo 2. Sharpened Stone (x2 Stones)
echo 3. Spear (x1 Rope, x1 Stick, x1 Sharpened Stone )
echo 4. Handaxe (x2 Rope, x2 Stick, x1 Sharpened Stone)
echo 5. Hammer (x2 Rope, x2 Stick, x1 Stone)
echo.
choice /c 12345
echo.
echo.
if %errorlevel%==1 (
set item=Rope
::item being crafted
set /a req1=%fiber_qty%
::1st required item
set /a min1=3
:: minimum amount needed to craft
set /a req2=0
set /a min2=0
set /a req3=0
set /a min3=0
set var1=fiber
::passes a string to be use for a vavriable
set var2=
set var3=
set var4=rope
)
if %errorlevel%==2 (
set item='Sharpened Stone'
set /a req1=%stone_qty%
set /a min1=2
set /a req2=0
set /a min2=0
set /a req3=0
set /a min3=0
set var1=stone
set var2=
set var3=
set var4=sharpened_stone
)
if %errorlevel%==3 (
set item=Spear
set /a req1=%rope_qty%
set /a min1=1
set /a req2=%stick_qty%
set /a min2=1
set /a req3=%sharpened_stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=sharpened_stone
set var4=spear
)
if %errorlevel%==4 (
set item=Handaxe
set /a req1=%rope_qty%
set /a min1=2
set /a req2=%stick_qty%
set /a min2=2
set /a req3=%sharpened_stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=sharpened_stone
set var4=handaxe
)
if %errorlevel%==5 (
set item=Hammer
set /a req1=%rope_qty%
set /a min1=2
set /a req2=%stick_qty%
set /a min2=2
set /a req3=%stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=stone
set var4=hammer
)
::////////////////////////////////////////////////////////////////////////////////////
:craftable_check
if %req1% GEQ %min1% (
if %req2% GEQ %min2% (
if %req3% GEQ %min3% (
::checks minimum requried material inventory for crafting
set /a %var1%_qty=!%var1%_qty!-%min1%
set /a %var2%_qty=!%var2%_qty!-%min2%
set /a %var3%_qty=!%var3%_qty!-%min3%
::uses all the required inventory for crafting
set /a %var4%_qty=!%var4%_qty!+1
::creates the crafted item
set /a inv_%var4%=1
::makes the new item is visible
if %req1% LEQ 0 (
set inv_%var1%=0
)
if %req2% LEQ 0 (
set inv_%var2%=0
)
if %req3% LEQ 0 (
set inv_%var3%=0
)
::makes the items ivisible if there is no inventory
set /a display_message=1
set message='You have successfully created a %item%!'
goto message
)
)
)
set /a display_message=1
set message=You dont have enough material for this
goto message
:://///////////////////////////////////////////////////////////////////////////////////
:message
cls
if %display_message%==1 (
echo %message%
pause
set /a display_message=0
goto start
)
::General Settings ------------------------------------------------------------------------------
#echo off
title Game Template
color 02
cd "%userprofile%\desktop"
::Game Settings ---------------------------------------------------------------------------------
:game_settings
cls
goto welcome
::Welcome Screen --------------------------------------------------------------------------------
:welcome
cls
echo Welcome to this Game!
echo/
echo Please select one of the options below
echo 1. New Game
echo 2. Load Game
echo 3. Credits
choice /c 123
if %errorlevel%==1 goto back_story
if %errorlevel%==2 goto load_game
if %errorlevel%==3 goto credits
goto welcome
::Save Game -------------------------------------------------------------------------------------
:save_game
cls
(
echo %location%
echo %player_name%
)>"GameSave.txt"
echo Game saved...
pause
goto :eof
::Load Game -------------------------------------------------------------------------------------
:load_game
cls
(
set /p location=
set /p player_name=
)<"GameSave.txt"
pause
goto %location%
::Back Story ------------------------------------------------------------------------------------
:back_story
cls
echo Backstory...
pause >nul
goto character_creation
::Character Creation ----------------------------------------------------------------------------
:character_creation
cls
echo What is your name?
set /p player_name=
if /i "%player_name%"=="" (
echo Player name can not be blank.
pause >nul
goto character_creation
)
goto start
::Game Start ------------------------------------------------------------------------------------
:start
cls
set location=start
echo %player_name%
echo %location%
echo/
echo 1. Pause Menu
choice /c 1
if %errorlevel%==1 goto pause_menu
goto start
::Pause Menu ------------------------------------------------------------------------------------
:pause_menu
cls
echo 1. Save Game
echo 2. Return
echo 3. Quit
choice /c 123
if %errorlevel%==1 call :save_game
if %errorlevel%==2 goto %location%
if %errorlevel%==3 goto exit
goto pause_menu
::Credits ---------------------------------------------------------------------------------------
:credits
cls
echo credits...
pause >nul
goto welcome
if %req3% GEQ %min3% (
::checks minimum requried material inventory for crafting
set /a %var1%_qty=!%var1%_qty!-%min1%
won't work properly - :: comments are actually broken labels (labels that cannot be reached with a goto) and break code blocks (parenthesised series of statements)
Reserve a prefix character for any variable that you may want to save to a file for reloading later. EG #
set #>filename
saves all of the variables that start # to the file in the form #whatever=something.
Reload with
for /f "delims=" %%e in (filename) do set "%%e"
Equally, you can set up scenario files by choosing another prefix character.
Clearing the current values of variables-beginning-# is
for/f "delims==" %%e in ('set # 2^>nul') do set "%%e="
which you do just before loading from file.
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \, Space or " - build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
set up a menu subroutine using choice
:menu
set "choices="
set /a choicecount=0
cls
:menu_next
set /a choicecount+=1
if defined choicetext[%choicecount%] echo %choicecount%. choicetext[%choicecount%]&set "choices=%choices%%choicecount%"
if %choicecount% lss 9 goto menunext
echo Q. Quit
choice /c q%choices% /N /M "%~1"
goto :eof
This way, you can set up the available choices in choicetext[?] (and clear them with
for/f "delims==" %%e in ('set choicetext[ 2^>nul') do set "%%e="
) then display the menu by executing
call :menu "Some message"
When `:menu" returns, you can then
GOTO Someplace%errorlevel%
which will goto someplace2 etc. Note that because q is always the first character of the choices, then q will always return errorlevel 1, hence the label :whatever1 will mean q was pressed. That way, you don't need to alter the quit code should you extend the menu.
(X for eXit works, too.)

Batch file keeps crashing at if statement

I am making a simple text game. Everything works fine until it gets to the if statement. I do not know what i am doing wrong.
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
Here I have re-written this to be in a form that uses Functions and uses the suggestions I provided to the original post as comments.
You know I assumed incorrectly that you had a purpose to using the labels, but given the way the question has give I think you would do well to not bother with them.
Here is a no-labels version:
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
echo.
echo "I see. That's a gnarly gash you've got there!"
) ELSE (
echo.
echo "Oh Good!"
)
PAUSE
GOTO :EOF
Here is the labels version. (I removed the comments explaining how it works and why the code is there so it isn't so cluttered for you.)
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
CALL :Hurt
) ELSE (
CALL :NotHurt
)
PAUSE
GOTO :EOF
:Hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
GOTO :EOF
:NotHurt
echo.
echo "Oh Good!"
GOTO :EOF
For this sort of thing I prefer by far using choice, and frequently use my menu macro that returns the selected option as a string in the variable option
below is a shell script that demonstrates the usage of a few macro's I frequently use.
#ECHO Off & Goto :main
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Functions * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:+------------------------------------------------------------------------------------------------+:
:ColorString
(For %%C in (%~1)Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31))
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
:ColorMenu
rem Set /A "RR=!random! %%195 + 60","GG=!random! %%195 + 60","BB=!random! %%195 + 60"
rem Set "%~1=%/E%38;2;!RR!;!GG!;!BB!m!%~1!%/E%0m"
Set "rV="& IF "!#A!"=="" (Set #A=32)
(For %%C in ("!%~1!")Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31)) & Set "%~1=!rV!"
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:main * Environment Definition * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Rem /* ensure correct environment for macro definitions */
Endlocal & Setlocal DISABLEdelayedexpansion
:+------------------------------------------------------------------------------------------------+:
For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
:+------------------------------------------------------------------------------------------------+:
Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set "ColLETTERS=Set "Rv="& Set "#A=31" & (For %%A in ("$Str")Do Set "Word=%%~A" & For %%B In (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z . + - _ [ ] / \ ":")Do Set "Word=!Word:%%~B=%%~B !") & (Call :ColorString "!Word!" & Echo/!rV!)"
Set "ColWORD/S=Set "#A=35"& Set "MSG=$Str" & For %%G in ("!MSG!")Do (For %%v in (%%~G)Do (Set "Rv="&Call :Colorstring "%%~v"& For %%x in (!Rv!)Do (Set "MSG=!MSG:%%~v=%/E%0m%%~x!")))&Echo/!MSG!"
Set "List/D/V=Set "#$L=0"&Set "$$L="&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Set "%%~G" > Nul &Set /A "#$L+=1"))Else Set $L="
Set "Menu=For %%n in (1 2)Do if %%n==2 (!DIV!&Set "CH#=0"&(Set "CHCS="&For %%G in (!Options!)Do For %%i in (!CH#!)Do (Set "CHCS=!CHCS!!ChoList:~%%i,1!"&Set "Opt[!ChoList:~%%i,1!]=%%~G"& Set "Opt=%%~G" &Call :ColorMenu Opt &<Nul Set /P "=[!ChoList:~%%i,1!] !Opt!"&Set /A "CH#+=1"&Echo/))&!DIV!& For /F "Delims=" %%o in ('Choice /N /C:!CHCS!')Do (Set "OPTION=!Opt[%%o]!"))Else Set Options="
Set "ColLINE=For %%n in (1 2)Do if %%n==2 (Echo/!$C!!$Str!%/E%0m)Else Set $Str="
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Script Body * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Setlocal EnableDelayedExpansion
for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
Set "DIV=Echo/%/E%33m!DIV!%/E%0m"
%List/D/V:$L=Colors%"Red=%/E%31m" "Yellow=%/E%33m" "Green=%/E%32m" "Blue=%/E%34m" "Purple=%/E%35m" "Cyan=%/E%36m" "White=%/E%37m" "Gray=%/E%90m" "Pink=%/E%91m" "Beige=%/E%93m" "Aqua=%/E%94m" "Magenta=%/E%95m" "Teal=%/E%96m" "Off=%/E%0m" "Black=%/E%30m"
%List/D/V:$L=Actions%"Buy a house=Did you win the lotto" "Go for a drive=Start your engines" "Walk on the wild side=Get mauled by a lion" "Run a mile=Fit yet" "flee the realm=fall down a hole" "battle trolls=A losing battle" "puzzle a conundrum=Enigma's Stigmatised" "solve 42=life is meaningless"
%ColLETTERS:$Str=Welcome.%
%ColWORD/S:$Str=Hello there my friend^! How are you today.%
%ColLINE:$C=Teal%What a world we live in^^!
%Menu%"Buy a house" "Go for a drive" "Walk on the wild side" "Run a mile" "flee the realm" "battle trolls" "puzzle a conundrum" "solve 42"
For %%G in ("!Option!")Do Echo/!%%~G!
The menu macro builds a list of choices for each argument it's supplied, using substring modification to iterate over a 36 character choice list to build the final choice options - meaning support for 36 menu options.
Update
An additional example has been added to show a way to use the selection to display output or take actions without requiring conditional testing. Using the List/D/V macro to define values to options, a selected OPTION can be expanded directly. In the example, it's just to display output, however values can be assigned containing simple commands like Set, Goto or call to perform specific actions for the chosen menu option.
I forgot to add pause
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
pause

Remotely get serial number and model from list in batch script

I am trying to create a simple script that will use computer name from pclist.txt and get serial number and model and export to csv file. I just can not seem to figure out why it does not print the serial number and model in the csv file. Here is my simple script.
#echo off
for /f %%i in (pclist.txt) do (
for /f "tokens=2 delims==" %%M in ('wmic /node:%%i csproduct get name /value') do set "Model=%%M"
for /f "tokens=2 delims==" %%I in ('wmic /node:%%i bios get serialnumber /value') do set "SN=%%I"
echo %%i, %SN%, %Model% >> list.csv
)
pause
I may have misunderstood what your intention was, but I would have expected the following to be the general way of achieving your intended task.
#%__AppDir__%wbem\WMIC.exe /Node:#pclist.txt /FailFast:1000 /Output:list.csv CSProduct Get Name /Format:CSV
#%__AppDir__%wbem\WMIC.exe /Node:#pclist.txt /FailFast:1000 /Append:list.csv BIOS Get SerialNumber /Format:CSV
#Pause
If you wanted to try to just output each item along side the node name separated by commas, then perhaps this will suffice:
#Echo Off
SetLocal EnableExtensions
(
For /F UseBackQDelims^=^ EOL^= %%G In (
"pclist.txt"
) Do (
For /F Tokens^=6Delims^=^" %%H In (
'%__AppDir__%wbem\WMIC.exe /Node:%%G /FailFast:1000 CSProduct Get Name /Format:MOF'
) Do (
For /F Tokens^=6Delims^=^" %%I In (
'%__AppDir__%wbem\WMIC.exe /Node:%%G /FailFast:1000 BIOS Get SerialNumber /Format:MOF'
) Do Echo %%G,%%H,%%I
)
)
)>"list.csv"
Pause
Your code would run fine - when wmic wouldn't have that ugly line ending of CRCRLF. The first CR becomes part of your variable. CR means "set the cursor back to the beginning of the line", so everything echoed after (in the same line) overwrites the previous content.
You can solve that with another for loop to strip the remaining CR. And you don't need the variables SN and Model; when you nest the for loops, you can use the for variables directly instead:
#echo off
del list.csv 2>nul
for /f %%i in (pclist.txt) do (
for /f "tokens=2 delims==" %%M in ('wmic /node:"%%i" csproduct get name /value') do for %%m in (%%M) do (
for /f "tokens=2 delims==" %%S in ('wmic /node:"%%i" bios get serialnumber /value') do for %%s in (%%S) do (
>>list.csv echo %%i, %%s, %%m
)
)
)
type list.csv
pause
(Compo's code works, because the desired string is cut from the middle of a line, so the line ending doesn't matter)

wshShell and WMIC working together in batch?

I was trying to create a scrollable list for a batch file using the method found here: Scrollable Lists in .bat Files
Credit to https://stackoverflow.com/users/778560/aacini
One I tried adding back in my code for my regular batch a few lines at a time, I noticed that the solution doesn't work when I use WMIC. What is the reason for this and is there an easy solution? You can run the below code and then un-comment the WMIC line and see it will not work anymore.
Edit: I am using Windows 7
Thanks!
#if (#CodeSection == #Batch) #then
#echo off
setlocal EnableDelayedExpansion
color F0
::FOR /F "tokens=2 delims==" %%A IN ('WMIC csproduct GET Name /VALUE ^| FIND /I "Name="') DO SET machine=%%A
Echo Reset or Continue
Set MenuOptions=RESET Continue
call :ShowMenu
pause
exit
:ShowMenu
set numOpts=0
for %%a in (%MenuOptions%) do (
set /A numOpts+=1
set "option[!numOpts!]=%%a"
)
rem Clear previous doskey history
doskey /REINSTALL
rem Fill doskey history with menu options
cscript //nologo /E:JScript "%~F0" EnterOpts
for /L %%i in (1,1,%numOpts%) do set /P "var="
rem Send a F7 key to open the selection menu
cscript //nologo /E:JScript "%~F0"
set /P "MenuSelected=Option Selected: "
echo/
#end
var wshShell = WScript.CreateObject("WScript.Shell"),
envVar = wshShell.Environment("Process"),
numOpts = parseInt(envVar("numOpts"));
if ( WScript.Arguments.Length ) {
// Enter menu options
for ( var i=1; i <= numOpts; i++ ) {
wshShell.SendKeys(envVar("option["+i+"]")+"{ENTER}");
}
} else {
// Enter a F7 to open the menu
wshShell.SendKeys("{F7}");
}
SendKeys Method sends one or more keystrokes to the active window. Unfortunately, Sendkeys() sometimes fails usually due to focus or timing, both troublesome and difficult to solve problems. I tried pause and timeout, tried WshShell.AppActivate in various combinations, all without success…
Finally, I found culprit in clearing previous doskey history via doskey /REINSTALL command: it installs a new copy of doskey. I can recommend more intuitive (and less invasive) method to clear the doskey command history buffer:
doskey /ListSize=0
doskey /ListSize=50
Bonus: FOR loops explanation.
outer %%A loop to retrieve the name property;
inner %%a loop to remove the ending carriage return in the value returned: wmic behaviour: each output line ends with 0x0D0D0A (<CR><CR><LF>) instead of common 0x0D0A (<CR><LF>).
Credit: Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem
Working script (Windows 8.1 64 bit):
#if (#CodeSection == #Batch) #then
#echo OFF
setlocal EnableDelayedExpansion
REM color F0
FOR /F "tokens=2 delims==" %%A IN ('
WMIC csproduct GET Name /VALUE ^| FIND /I "Name="
') DO FOR %%a in ("%%~A") DO SET "_machine=%%~a"
Echo Reset or Continue %_machine%
Set "MenuOptions=%_machine% RESET Continue" expanded merely for debugging purposes
call :ShowMenu
REM pause
exit /B
:ShowMenu
set numOpts=0
for %%a in (%MenuOptions%) do (
set /A numOpts+=1
set "option[!numOpts!]=%%a"
)
rem Clear previous doskey history
REM this causes problems: doskey /REINSTALL
doskey /ListSize=0
doskey /ListSize=50
rem Fill doskey history with menu options
cscript //nologo /E:JScript "%~F0" EnterOpts
for /L %%i in (1,1,%numOpts%) do set /P "var="
rem Send a F7 key to open the selection menu
cscript //nologo /E:JScript "%~F0"
set /P "MenuSelected=Option Selected: "
echo/
goto :eof
#end
var wshShell = WScript.CreateObject("WScript.Shell"),
envVar = wshShell.Environment("Process"),
numOpts = parseInt(envVar("numOpts"));
if ( WScript.Arguments.Length ) {
// Enter menu options
for ( var i=1; i <= numOpts; i++ ) {
wshShell.SendKeys(envVar("option["+i+"]")+"{ENTER}");
}
} else {
// Enter a F7 to open the menu
wshShell.SendKeys("{F7}");
}

Replace substring in text file with a batch script

I need to deploy a batch update to hundreds of services via our Control Panel, and need to replace a sub-string in a specific file when doing so. How can I use a batch file to change the following and rewrite it to the same file rather than a new file?
hostName = "Server UK (Public/Veteran) 116621";
to
hostName = "Server UK (Public/Veteran) 224421";
Here is another way to do it with pure batch. This does write to another file but then moves it without prompting, overwriting the original with the changes.
#echo off
setlocal enabledelayedexpansion
(for /f "tokens=*" %%f in (file.cfg) do if not "%%f"=="" (
set "line=%%f"
set "line=!line:116621=224421!"
echo(!line!
)) > tmp.cfg
Move /y tmp.cfg file.cfg
And here is a way with a Hybrid VBS/Batch
#echo off
setlocal
call :FindReplace "116621" "224421" file.cfg
exit /b
:FindReplace <findstr> <replstr> <file>
set tmp="%temp%\tmp.txt"
If not exist %temp%\_.vbs call :MakeReplace
for /f "tokens=*" %%a in ('dir "%3" /s /b /a-d /on') do (
for /f "usebackq" %%b in (`Findstr /mic:"%~1" "%%a"`) do (
echo(&Echo Replacing "%~1" with "%~2" in file %%~nxa
<%%a cscript //nologo %temp%\_.vbs "%~1" "%~2">%tmp%
if exist %tmp% move /Y %tmp% "%%~dpnxa">nul
)
)
del %temp%\_.vbs
exit /b
:MakeReplace
>%temp%\_.vbs echo with Wscript
>>%temp%\_.vbs echo set args=.arguments
>>%temp%\_.vbs echo .StdOut.Write _
>>%temp%\_.vbs echo Replace(.StdIn.ReadAll,args(0),args(1),1,-1,1)
>>%temp%\_.vbs echo end with
just try sed for Windows
for %%a in (*.txt) do sed -ri.bak "s#hostName = \"Server UK \(Public/Veteran\) 116621\"#hostName = \"Server UK (Public/Veteran) 224421\"#g" "%%~a"
You can use this routine to replace a string with another string in a file, saving in a separate file or overwriting the original, just past the fourth parameter to save it in a separate file, otherwise, do not pass the parameter and will be replaced with the new content.
#echo off
#break off
#title Replace substring in text file with a batch script - D3F4ULT
#color 0a
#cls
:: Routine to replace an input string by a string output in the contents of a file.
setlocal EnableDelayedExpansion
REM Examples
REM call:replace-string-file-from-to "config.cfg" "116621" "224421"
REM call:replace-string-file-from-to "config.cfg" "116621" "224421" "config.cfg"
REM call:replace-string-file-from-to "config.cfg" "116621" "224421" "configuration.dat"
REM call:replace-string-file-from-to "%UserProfile%\Downloads\config.cfg" "116621" "224421" "%UserProfile%\Downloads\configuration.dat"
REM Calling Routine
call:replace-string-file-from-to "config.cfg" "116621" "224421"
exit
:replace-string-file-from-to
:: %~1 = File [In] [Mandatory]
:: %~2 = From [In] [Mandatory]
:: %~3 = To [In] [Mandatory]
:: %~4 = Out [Out] [Optional]
REM Mandatory Parameters
if "%~1" EQU "" echo Error %%~1 not defined&&echo.&&ping -n 4 localhost>nul&&exit /B 1
if "%~2" EQU "" echo Error %%~2 not defined&&echo.&&ping -n 4 localhost>nul&&exit /B 1
if "%~3" EQU "" echo Error %%~3 not defined&&echo.&&ping -n 4 localhost>nul&&exit /B 1
if exist "%~dpnx1" (
set "INPUT_FILE_LOCATION=%~dpnx1"
cd /D "%~dp1"
) else if exist "%~dp0\%~nx1" (
set "INPUT_FILE_LOCATION=%~dp0%~nx1"
cd /D "%~dp0"
) else if exist "!CD!\%~nx1" (
set "INPUT_FILE_LOCATION=!CD!\%~nx1"
cd /D "!CD!"
)
if not defined INPUT_FILE_LOCATION (
echo ERROR
echo.
echo File not found = '%~nx1'
echo.
echo Exiting...
echo.
ping -n 8 localhost>nul
exit /B 1
)
set "INPUT_FILE_FOLDER=%~dp1"
set "INPUT_FILE_NAME=%~n1"
set "INPUT_FILE_EXTENSION=%~x1"
if "%~4" EQU "" (
set "OUTPUT_FILE_LOCATION=!INPUT_FILE_FOLDER!!INPUT_FILE_NAME!__new__!INPUT_FILE_EXTENSION!"
set "INOUT_DEL_MOVE=true"
) else if "%~dpnx1" EQU "%~dpnx4" (
set "OUTPUT_FILE_LOCATION=!INPUT_FILE_FOLDER!!INPUT_FILE_NAME!__new__!INPUT_FILE_EXTENSION!"
set "INOUT_DEL_MOVE=true"
) else (
set "OUTPUT_FILE_FOLDER=%~dp4"
set "OUTPUT_FILE_NAME=%~n4"
set "OUTPUT_FILE_EXTENSION=%~x4"
set "OUTPUT_FILE_LOCATION=!OUTPUT_FILE_FOLDER!!OUTPUT_FILE_NAME!!OUTPUT_FILE_EXTENSION!"
)
if exist "!OUTPUT_FILE_LOCATION!" (
del /f /q "!OUTPUT_FILE_LOCATION!">nul
)
for /F "usebackq tokens=*" %%A in ( "!INPUT_FILE_LOCATION!" ) do (
set "string=%%~A"
set "string=!string:%~2=%~3!"
echo !string!>>"!OUTPUT_FILE_LOCATION!"
)
if defined INOUT_DEL_MOVE (
if exist "!INPUT_FILE_LOCATION!" (
del /f /q "!INPUT_FILE_LOCATION!">nul
)
if exist "!OUTPUT_FILE_LOCATION!" (
move /y "!OUTPUT_FILE_LOCATION!" "!INPUT_FILE_LOCATION!">nul
)
)
goto:eof