How would I set a each line of a text document to separate variables using Batch? I know how to set a variable to the first line of a text document using:
Set /p Variable=<Test.txt
…but I don’t know how to read other lines of the file. Lets say for example I had a text document with 3 lines, the first line had ‘Apples’ written on it, the second had ‘Bananas’ and the third had ‘Pears’, and lets say the document was called Fruit.txt. How would I set the variable ‘Line_1’ to the first line of the document, ‘Line_2’ to the second line and ‘Line_3’ to the last line?. Just to keep it simple, lets just say the batch file and Fruit.txt are both in the same folder. I don’t want to do this in VBScript, so please only post Batch code. I would have thought that it would be something like:
@Echo off
Set /p Line_1=<Fruit.txt:1
Set /p Line_2=<Fruit.txt:2
Set /p Line_3=<Fruit.txt:3
Echo Fruit 1 is %Line_1%, Fruit 2 is %Line_2% and Fruit 3 is %Line_3%
Pause
Exit
…but quite clearly it isn’t. Any help?
EDIT: This is for arbitrary-length files, then. jeb has an answer that solves your particular problem for a known number of lines. I will leave this here, though, as I hate deleting posts I put some time into for explanation 🙂
Well, you obviously need some sort of counter. Let’s start with 1:
Then, you need to go line-wise through the file:
Then store the line in a numbered variable (that’s what we have the counter for):
aaaaand increment the counter:
And that’s it. Add a few more necessary things, you know, the boring stuff that’s always needed in such cases (strange statements before and after, block delimiters, etc.), and you’re done:
Some explanation:
set /p Var=<filewill set the variable to the first line of a file, as you noted. That works becauseset /pwill prompt for input and< filewill redirect the file into standard input of a command. Thusset /pwill interpret the file’s contents as the entered input up until the user hits Return (i.e. the file contains a line break). That’s why you get the first line. The system would throw the whole file atset /pbut since the command only reads the first line and then is done they just get discarded.The syntax you were proposing there is actually for accessing Alternate Data Streams of files on NTFS, which is somethhing totally different.
<short-detour>However, jeb has a way of reading multiple lines. This works because the block (delimited by parentheses) is a single command (see below) you can redirect a file’s contents into. Except that command is comprised of multiple statements, each of which will read a single line and store it away.</short-detour>Which brings us to
for /fwhich iterates over the contents of a file (or the output of a command) line by line and executes a command or block of commands for each line. We can now read the whole file into as many variables as there are lines. We don’t even need to know how many in advance.You may have noticed the
Line_!Counter!in there which usesCountera little bit differently from how you’re used to use environment variables, I guess. This is called delayed expansion and is necessary in some cases due to howcmdparses and executes batch files. Environment variables in a command are expanded to their values upon parsing that command. In this case the wholefor /fincluding the block containing two statements is a single command forcmd. So if we used%Counter%it would be replaced by the valueCounterhad before the loop (1) and never change while the loop is running (as it is parsed once and run multiple times. Delayed expansion (signaled by using!instead of%for variable access changes that and expands environment variables just prior to running a command.This is almost always necessary if you change a variable within a loop and use it within the same loop again. Also this makes it necessary to first enable delayed expansion which is done with the
setlocalcommand and an appropriate argument:set /awill perform arithmetic. We use it here to incrementCounterby one for each line read.