Why doesn't my text grabber work in batch? - batch-file

I am developing a program in batch that will play the board game Talisman (second edition). It is in very early development and not ready for testing.
At one point in the code I need to print the top line of a text document. This part of the code looks like this:
find /I "alchemy" priorities.txt >nul
if %errorlevel%==0 (
set /p alchemObj=< 2Alchemise.txt
echo I will visit the alchemist in the city.
echo.
echo The Alchemist converted my %alchemObj% into 1 gold
set /a gold=%gold%+1
echo I now have %gold% gold.
for /f "skip=1 delims=*" %%a in (2Alchemise.txt) do (
echo %%a >>newfile.txt
)
xcopy newfile.txt 2Alchemise.txt /y >nul
del newfile.txt /f /q >nul
)
When this program is run everything except the
echo The Alchemist converted my %alchemObj% into 1 gold
seems to work. When it is run it prints "The Alchemist converted my into 1 gold"
I have tried running:
set /p alchemObj=< 2Alchemise.txt
and then
echo The Alchemist converted my %alchemObj% into 1 gold
and it seems to work just as expected.
Thanks for your help, Edje
(Click here to download whole file)

Thanks a lot to michael_heath for their answer.
I was using delayed expansion for an earlier part of the code. For what ever reason I needed to use the '!' variable deliminator instead of the default '%' deliminator.
Thanks also to Squashman and Mofi as I used these suggestions to improve my code further.
Thanks a lot this have given me a great first impression of Stack Overflow.
Evyn

Related

Pull string from text file and rename the file using that text. For /F? Delims?

Hello I am a little out of my depth here so hence the question. I have tried reading past post but due to my unfamiliarity I am unable to adapt other solutions into mine. I also don't really have proper code in place but I'm hoping that because my question seems simple maybe someone can help me or direct me. Thank you.
I have a program that exports EDI data into a file called FOUT_R.edi and I need a batch script that will look into the file, pull the string from line 4 value 3 and line 7 value 3 and then rename the file using the combined values. The values are asterisks delimited. Below is a sample...
ISA*00* *00* *ZZ*JK60 *ZZ* MFG *:
GS*IN*JK60* MFG*20170223*1531*1*X*004010
ST*810*0001
BIG*20170223*237454
CUR*SE*CAD
REF*SI*238972
N1*ST*VEHICULOS COMERCIALES MEXICO S.A. DE C.V*92*065
N1*SU*METAL*92*JK60
DTM*011*20170223
So in the end I want the file name to read
"237454 VEHICULOS COMERCIALES MEXICO S.A. DE C.V.edi"
(.edi being the file extension). Again not sure what I'm doing, my starter scripts look like this
for /f "delims=*" %%fname1 IN (FOUT_R.edi) DO ren FOUT_R.edi %%fname1.edi
but it's obviously wrong it was just a starting spot for me but I realize now that this is out of my league.
Can someone please help or direct me to a site where the most inexperienced scripters can be explained in baby steps?
thank you.
Provided the name in line 7 doesn't contain colons, this should do:
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
set "FileName=FOUT_R.edi"
set "NewName="
for /f "tokens=4 delims=:*" %%A in (
'findstr /N "^" "%FileName%" ^|findstr "^4: ^7:"'
) Do Set "NewName=!NewName! %%A"
Echo Ren "%FileName%" "%NewName:~1%.edi"
timeout -1
If the output looks ok, remove the Echo
#echo off
setlocal
set "filename=FOUT_R.edi"
for /F "skip=3 tokens=3 delims=*" %%a in (%filename%) do set "Line4value3=%%a" & goto break1
:break1
for /F "skip=6 tokens=3 delims=*" %%a in (%filename%) do set "Line7value3=%%a" & goto break2
:break2
ren %filename% %Line4value3%%Line7value3%.edi
Sorry, no explanations; look for they yourself: open a command-prompt session and type the command followed by /?.
Note that if the file name may contain spaces, it must be enclosed in quotes.

Randomly choose between two names in batch

I'm trying to get a batch script to randomly choose between two names and output one at a time, kinda something like this:
#echo off
::I would not be prompted to enter these, they would already be programmed into the script.
ChooseRandomSet=Maria
Sean
Matt
Laura
ChooseRandom
So, then on the user side, you would see:
C:\>script.bat
Matt was randomly chosen.
C:\>script.bat
Sean was randomly chosen.
C:\>
Thanks!
First create a text file with all the names on separate lines:
Maria
Sean
Matt
Laura
Then create a .bat file with the following code:
#ECHO OFF
IF "%~1"=="" (ECHO No text file specified & GOTO :EOF)
IF NOT EXIST %1 (ECHO Text file doesn't exist. & GOTO :EOF)
FOR /F "" %%I IN ('FIND /C /V "" ^<%1') DO SET /A lines=%%I
IF %lines%==0 (ECHO Text file is empty or unreadable & GOTO :EOF)
SET /A skip=(%RANDOM%*32768+%RANDOM%)%%lines
<%1 (
FOR /L %%I IN (1,1,%skip%) DO (
SET /P line=
)
SET line=
SET /P line=
)
ECHO(%line%
This will print out a name from the file, it will also check for certain errors like:
No text file specified
File specified but non-existent
Empty text file
Disclaimer:
I used this bat script for something but I didn't write it, I might've changed a few things over the years but it's largely as I found it a while back. (not a Windows guy myself.. :P)
Update: I also found an answer to this myself just by experimenting. This chooses one option out of two possible choices:
#echo off
if %random% gtr %random% (
echo heads
) else (
echo tails
pause

How to exit a user input loop in batch?

Well I have a simple for loop to take user input and creat a file with this input, then ask for the next input and create "file2" etc., but I can't seem to figure out how my user can quit the loop with a certain input (maybe "exit" or "end").
setlocal enabledelayedexpansion
set x=1
:runName
set /p names="Enter header for file !x!:"
for %%a in (%names%) do (>>file!x!.txt (echo %%~a) set /a x+=1)
if !names!=end goto:eof else goto:runName
:eof
echo press any key to close
pause>nul
Ps. Sorry for the poor formatting, I cant figure how to enter my code in the grey field from my phone and dont have a computer at the moment.
I'm not quite shure why the input prompt says header.
Here is my best guess what you may have meant:
#Echo off
setlocal enabledelayedexpansion
set x=1
:runName
Set "names="
set /p names="Enter header for file%x%:"
if not defined names goto :end
if /I "%names%" Equ "end" goto :end
(
for %%a in (%names%) do (echo:%%~a)
) >file!x!.txt
set /a x+=1
goto :runName
:end
echo press any key to close
pause>nul
Running
Enter header for file1:anton bertha caesar
Enter header for file2:anchorage berlin
Enter header for file3:END
press any key to close
File content
> type file*.txt
file1.txt
anton
bertha
caesar
file2.txt
anchorage
berlin
I can't seem to figure out how my user can quit the loop
If you'll allow a suggestion, mine would be don't do that.
Almost any batch script is best written to accept command-line options and files as input. Once you trap the user into providing input interactively -- anything more than Y or N, and even that's a nuisance -- you're putting him in a bad spot. He can't re-run your script without going through the tedium again. He can't use tab completion, or pick from a list. He's trapped in a user-interface element that hasn't been improved in 30 years, and wasn't very good then.
I don't know what to suggest specifically. The example you provide is so trivial it would be easier to provide the file directly using Notepad than to create it with a script. Then you might want a verification script to make sure the provided input file is valid.
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /f "SKIP=0 EOL=; TOKENS=* DELIMS=" %%i in ('dir /b c:\windows\*.* ^|FIND /i *.exe') do (
CHOICE /D N /T 5 /C YN /M "Please pre Y to exit"
IF !ERRORLEVEL!==1 GOTO :END
IF !ERRORLEVEL!==2 ECHO CONTINUE
timeout 5
#echo %%i
)
:END
ENDLOCAL

"Echo is On" Output to text file blank

for /f %%C in ('Find /V /C "" ^< mamegamelist.txt') do set Count=%%C
echo The file has %Count% lines.
echo %Count%>gamecount.txt
set /p texte=< mamegamelist.txt
echo %texte%>currentgame.txt
set/a played=3379-%Count%
echo %played%>played.txt
pause
Everything works fine except for this line:
set/a played=3379-%Count%
echo %played%>played.txt
It evaluates correctly, but it doesn't write out anything to the file.
If I change the arithmetic expression to something like this:
set/a played=%Count%+2
echo %played%>played.txt
It will work perfectly fine. I'm pretty sure I don't have any unnecessary spaces anywhere. Any help appreciated!
You don't tell us what numbers you are using.
If mamegamelist.txt is empty or has fewer than 10 lines, you get an echo is off message from the first redirected echo.
A single digit before a redirector redirects an output stream to the file. Somethimes the syntax can be tricky to formulate.
Try
>played.txt echo %played%
(and follow the bouncing ball for any other possible exactly-1-digit-before-a-redirector instructions, like to gamecount.txt)
By placing the redirector at the start of the line, any problem with the syntax is avoided.

CLS (clear) a single line?

Is there any way to CLS a single line of output? I don't believe there are any switches for CLS, so maybe a better question would be:
Is there any way to
retain all previous output for re-use?
or
capture currently displayed output (like you can by marking and copying)?
I'm just trying to make my scripts a little more user-friendly by having real-time feedback / information, instead of multiple lines with slight changes. The only way I can think of doing this, though, is like this:
#echo off
goto Prep
:Prep
SET count=5
SET genericMessage=This window will close
goto Output
:Output
IF NOT %count% == -1 (
cls
IF %count% == 0 (
echo %genericMessage% now.
) ELSE (
echo %genericMessage% in %count% seconds.
)
SET /A count=%count% - 1
ping localhost -n 2 >nul
goto Output
) ELSE (
exit
)
So, you get this:
The problem with this, though, is that CLS erases all output, when I only want to refresh one line by erasing and re-outputting it.
Anyone have any ideas?
If you only need to move the cursor in one line (like your sample),
it's possible with a carriage return character.
#echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
for /L %%n in (5 -1 1) do (
<nul set /P "=This window will close in %%n seconds!CR!"
ping -n 2 localhost > nul
)
Unfortunately, there is no native command or utility that repositions your cursor in a Windows command line console.
You will need a 3rd party utility.
Aacini posted a free CursorPos.exe utility on DOSTips. The CurorPos.exe "source" is given as Hex digits. To use the source you will need the HexToBin.bat "compiler".
Browse both threads and you will find a number of utilities you may find useful.
Try ANSI sequences: http://www.robvanderwoude.com/ansi.php
Burrowing down the links, http://batch.xoo.it/t2238-BG-exe-Utility-for-Batch-Games.htm looks the most promising.
This page sounds like it has useful discussion on controlling/setting console sizes (and other display and buffer size settings). http://www.pcreview.co.uk/forums/change-buffer-size-console-window-can-runas-inherit-console-props-t1468842.html
An alternative quick&dirty method of moving the cursor via TIMEOUT:
#echo off
<nul set/p"=5 seconds till i close..."
timeout /t 5 /nobreak >con
echo(i'm closing now...[REPLACE this with lots of spaces]
exit /b

Resources