0

I have a batch file which is performing a series of functions for each item in a file. It's running correctly, however, for some reason, it's performing the operation for the last line in the file twice. Can anyone help me determine why? This is the first for loop I've made on my own, so I'm sure I've made some mistakes.

for /F "tokens=*" %%A in (nations.txt) do (
set "nationname=%%A"
call :ageofdiscovery
)

Point of clarification, what I am trying to do is call each and every line of "nations.txt" one at a time, storing them as a variable, then performing an elaborate series of operations using that variable, before moving on to the next line, and running through the whole of "nations.txt". The idea is to allow the script to work for an arbitrary number of loops, so as to make the script more flexible (It's a text generator, creating histories for fantasy kingdoms).

If there is no problem with the for loop, could someone explain why it's repeating the last output? I have an exit command after the loop, so it shouldn't be executing the script again, and it also has the same random generated output for the repeated last line.

EDIT: As requested, the current contents of nations.txt is:

Nation1
Nation2
Nation3
Nation4

As for the batch script itself, it's 2,134 lines long (and runs perfectly fine with a hard-coded version of the nation selection system. I'm retrofitting code here). I'm unsure of what, or where, any problems could be occurring. I also know that people here do not want me to share the entire script. I will do as requested in relation to the script itself.

  • 1
    There seems to be no problem with what you've posted. Perhaps a few more lines might reveal something...Also, copy/pasting the last few lines of `nations.txt` would allow others to duplicate results - I couldn't. Perhaps changing `tokens=*"` to `delims="` might change things. I'd change the subroutine to just one line, `ECHO ++%nationname%++&pause&goto :eof` - the `++` I use so that any invisible characters (like backspace, for instance) can be discovered. Also, follow the loop with `echo ---------&pause` which will show whether to loop is exiting correctly. – Magoo Jun 11 '22 at 03:39
  • @magoo The file is 2,137 lines long. I'm not sure where the problem could be, or how to find out. I don't want to burden people with reading through all that :/ I'll try your steps out. As for the contents of nations.txt it's just "Nation1 Nation 2 Nation3 Nation4" with each Nation on its own line. – Meep the Changeling Jun 11 '22 at 03:58
  • That's why I asked for `**the last few lines** of `nation.txt` - about 4 would do, copy/pasted into your question – Magoo Jun 11 '22 at 04:09
  • @Magoo added them, as well as clarifed it's the script that's 2,137 lines long, not the contents of nations.txt – Meep the Changeling Jun 11 '22 at 04:17
  • Did you try removing as much stuff as possible in order to have the bare minimum code and text file needed to reproduce the issue? Something like `for /F "tokens=*" %%A in (nations.txt) do ( echo %%A )`. That `for` alone, does it have the issue you mentioned? Does the text file have an empty line at the end, or is the actual last character the `4` of `Nation4`? – Andrew Jun 11 '22 at 04:26
  • @Andrew Yes, I tried that, no there isn't an empty line at the end of the file. It still repeated the final entry. Hence, why I thought something was wrong with my for loop. – Meep the Changeling Jun 11 '22 at 04:28
  • I just created a batch file with an `@echo off` and then the `for` from my comment, created the txt file as your example and it worked just fine. Can you confirm that **this exact scenario** also fails for you? It shouldn't, really. – Andrew Jun 11 '22 at 04:34
  • @Andrew In that configuration, with only a CD command added to point it to nations.txt's dir, it works fine. My test.bat for this project includes some environment variables that I test under since the final product has them. Would any of these break the for? %SystemRoot%\System32\chcp.com 437 >nul chcp 65001 – Meep the Changeling Jun 11 '22 at 04:42
  • When you have weird scenarios like this, if you have a failing version and a working version, try your best to make both closer to each other, until you can find what's causing the problem. I don't think the `chcp` could be the cause, I tried running both `chcp.com 437` and `chcp 65001` (btw, why two?) and the result was the same. – Andrew Jun 11 '22 at 04:50
  • So - what was the result of adding the debugging that I asked for in my first comment? – Magoo Jun 11 '22 at 04:54
  • @Magoo the problem persisted, as I didn't think to use a test.bat without those environmental variables. Sorry, I can be an idiot sometimes. – Meep the Changeling Jun 11 '22 at 05:01
  • @Andrew Because without those two, I cannot use all of Unicode for some reason. With one, I can do box drawing if needed. With the other, I can use expanded character sets. I do lots of menus and often use IPA symbols as I make text generators that often require made-up words, so I reuse a batch file that generates a basic conlang using IPA symbols for things like place names. TLDR; I know one or other should do it, but it doesn't, so I use both. – Meep the Changeling Jun 11 '22 at 05:01
  • @MeeptheChangeling, did you check the answer from @jeb? If not, did you try what I said in my first sentence in my previous comment? – Andrew Jun 13 '22 at 13:41
  • @Andrew I don't get email notifications for this site, so I didn't notice I had an answer. I already had an exit before my subroutines :c – Meep the Changeling Jun 14 '22 at 23:04
  • @MeeptheChangeling, did you try what I said in the first sentence in my previous comment from June 11? – Andrew Jun 15 '22 at 12:56
  • @Andrew Yes, and I thought I had communicated that to you in my response to your comment. "In that configuration, with only a CD command added to point it to nations.txt's dir, it works fine." I then stated it breaks for some reason in the thing I need it for, and that I did not understand why. – Meep the Changeling Jun 16 '22 at 11:22
  • That was an earlier comment. I refer to *"try your best to make both closer to each other, until you can find what's causing the problem"*. Add stuff to the working one until it fails, or remove stuff from the failing one until it works. That way you can find the exact cause. Although now I see you accepted the answer. Was `exit` the problem? – Andrew Jun 17 '22 at 05:02
  • @Andrew No. I'm not sure what it was, but I had to re-write the entire script module by module to get it working. I probably had some logic somewhere in the 6000 lines that was breaking out of the loop. – Meep the Changeling Jun 17 '22 at 21:56
  • Well, so I'm afraid we might never know what was wrong exactly, and you accepted that answer just to thank for the effort I guess. XD – Andrew Jun 22 '22 at 09:25

1 Answers1

2

The best guess for your observed phenomenon is that your function is defined directly after your loop (you don't show that important detail).

for /F "tokens=*" %%A in (nations.txt) do (
  set "nationname=%%A"
  call :ageofdiscovery
)

:ageofdiscovery
echo %nationname%

In that case, the function code will be executed after the loop is finished, because batch-files don't have a concept of functions, they only know labels.

It can be easily fixed by an exit /b or goto :eof

for /F "tokens=*" %%A in (nations.txt) do (
  set "nationname=%%A"
  call :ageofdiscovery
)
exit /b

:ageofdiscovery
echo %nationname%
jeb
  • 78,592
  • 17
  • 171
  • 225