Create a text file 1 by 1 and save it to directory - batch-file

I have this command:
For /l %%n in (1,1,1) do echo welcome >> "C:\Users\Documents\Backup\TestingFile%%n.txt"
It creates a file and when you run it the next time it overwrites. It should create a file on each run.
For instance you run a script for two times it should 2 files but it does not.
Could anyone please help me?

Turns out you are asking the FOR command to count...
starting from one
stepping by one
ending at one.
So the FOR is doing what you asked it to, so getting just one file kind of makes sense. Let's ignore the file output part for a moment and see what the FOR is doing.
Here is an excerpt from the FOR command/s help text:
C:\tmp>for /?
...etc...
FOR /L %variable IN (start,step,end) DO command [command-parameters]
The set is a sequence of numbers from start to end, by step amount.
So (1,1,5) would generate the sequence 1 2 3 4 5 and (5,-1,1) would
generate the sequence (5 4 3 2 1)
Just for fun, let's skip the "write to a file part" and look at what the for loops are doing...
The original for loop is first with Welcome, then a slightly modified one with "more welcome"
Make sense?
C:\tmp>type foo.bat
echo off
For /l %%n in (1,1,1) do echo welcome, n=%%n
For /l %%n in (1,1,3) do echo ** more welcome, n=%%n **
C:\tmp>foo.bat
C:\tmp>echo off
welcome, n=1
** more welcome, n=1 **
** more welcome, n=2 **
** more welcome, n=3 **
C:\tmp>

If you want the batch file to create a new file each time it is run you will need to check for the existence of all the previous files first.
#echo off
set num=0
:LOOP
set /a num+=1
IF EXIST "C:\Users\Documents\Backup\TestingFile%num%.txt" GOTO LOOP
echo welcome >"C:\Users\Documents\Backup\TestingFile%num%.txt"
The flaw in this code though is that if you have 4 files created and someone deletes file 2 or 3, the next time it runs it will create that file instead of file 5.

Related

Concatenated text file output from single ECHO command gets characters inserted into string printed a second time after expected output

I'm trying to create a batch file to insert a string from a .txt file at a specific place inside a string in 225 batch files - i.e., inserted into one line in the file at a specific place - but this question concerns the inserting part, and not the loop part, so I've left out the latter in my code example. It's also currently just displaying the text on-screen; not actually writing it to files.
The target files are a bunch of launch .bat files used for running a game server cluster using a tool, so I will have to leave each of them with the same names as they start with (Start XXYY.bat). They contain something along these lines:
start /high ShooterGame\Binaries\Win64\ShooterGameServer.exe Ocean?ServerX=0?ServerY=0?AltSaveDirectoryName=0000?ServerAdminPassword=1234?MaxPlayers=50?ReservedPlayerSlots=25?QueryPort=50002?Port=5002?SeamlessIP=192.168.1.225?RCONEnabled=true?RCONPort=28450 -log -server -NoBattlEye
exit
Where the ServerX, ServerY, AltSaveDirectoryNamen and all three Port settings are unique to each server, so these will have to remain unchanged.
I need to add several more settings, from another .txt file in the final version, but for this example I will just put the additions (the word INSERT added after the ReservedPlayerSlots setting, while keeping each setting divided by question marks) directly into this script.
My code is actually doing exactly what I want it to, but unfortunately it doesn't stop at that point, and decides to append more text than I wanted; specifically, everything I add to the ECHO command which is not a variable name.
To clarify, I get the exact output that I want... Plus the unwanted addition of a bunch of question marks and the word INSERT, which apparently come from my ECHO command, but I just have no idea why they get re-added.
My knowledge of batch scripting is fairly limited, so there might well be something basic that I've overlooked.
I've tried replacing the question marks in the output (which are required to be questions marks in the final version) with normal letters instead, but it doesn't change the behaviour; they were still appended to the expected output, just like the question marks they replaced.
#ECHO OFF
SET FileNum=0000
REM I will have the code loop through 225 files (0000-1414) in the final version, but for test purposes I just set it to one single file number manually here.
SET FileName=Start %FileNum%.bat
REN "%FileName%" temp.txt
FOR /F "tokens=1,2,3,4,5,6,7,8,9,10,11,12 delims=?" %%a IN (temp.txt) DO (
ECHO %%a?%%b?%%c?%%d?%%e?%%f?%%g?INSERT?%%h?%%i?%%j?%%k?%%l
)
REN temp.txt "%FileName%"
I expect this code to output this:
start /high ShooterGame\Binaries\Win64\ShooterGameServer.exe Ocean?ServerX=0?ServerY=0?AltSaveDirectoryName=0000?ServerAdminPassword=1234?MaxPlayers=50?ReservedPlayerSlots=25?INSERT?QueryPort=50002?Port=5002?SeamlessIP=192.168.1.225?RCONEnabled=true?RCONPort=28450 -log -server -NoBattlEye
exit
But what I am getting is this:
start /high ShooterGame\Binaries\Win64\ShooterGameServer.exe Ocean?ServerX=0?ServerY=0?AltSaveDirectoryName=0000?ServerAdminPassword=1234?MaxPlayers=50?ReservedPlayerSlots=25?INSERT?QueryPort=50002?Port=5002?SeamlessIP=192.168.1.225?RCONEnabled=true?RCONPort=28450 -log -server -NoBattlEye
exit???????INSERT?????
Which is the expected output, but with the unexpected re-addition of every symbol in the ECHO command which did not designate a variable at the end of the output (in this case ???????INSERT?????), just after the exit.
I'm stumped... I hope someone has an idea what I'm doing wrong here.
Okay, I applied the idea that aschipfl provided, and it seems to work now.
The IF NOT "%%b"=="" line seems to have done the trick, after I added the final line with the exit using another ECHO. My full script (including loop and write to file) is now like this:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "Insert=SettingOne=True?SettingTwo=False?SettingThree=1.000000"
FOR /l %%x IN (0, 1, 14) DO (
FOR /l %%y IN (0, 1, 14) DO (
IF %%x LSS 10 (SET XNum=0%%x) ELSE (SET XNum=%%x)
IF %%y LSS 10 (SET YNum=0%%y) ELSE (SET Ynum=%%y)
SET "FileNum=!XNum!!YNum!"
SET "FileName=Start !FileNum!.bat"
ECHO Filename: !FileName!
REN "!FileName!" temp.txt
(
FOR /F "tokens=1-12 delims=?" %%a IN (temp.txt) DO (
IF NOT "%%b"=="" (
ECHO %%a?%%b?%%c?%%d?%%e?%%f?%%g?%Insert%?%%h?%%i?%%j?%%k?%%l
ECHO exit
)
)
) >edited.txt
REN edited.txt "!FileName!"
DEL /q temp.txt
ECHO has been updated
)
)
This is now working exactly as intended.
It's quite possible that there is a more elegant way of doing this, and I am cartain that there is a way of making this more general and less hard-coded, but it's good enough for my purposes.
I thank you for your help!

currently using batch command, is it possible to point to a table of values?

i am using batch commands to generate a list of text in a mylist.txt file. eg.
\\abc\asd
\\def\as
\\ghi\as
i currently have a list of data (about 2500 rows), a few values/columns each row that contains static information (similar to a database). the list is currently in csv format.
for example:
\\abc\asd 123 home
\\def\as 456 office
\\ghi\as 789 elsewhere
i need to match the values in the mylist.txt and use it to execute a batch command. may i know how can i go about doing this?
i was thinking of using function, meaning each function will be named as one of the variable's values.
eg. one of the functions will be called "\abc\asd". and when the mylist.text has the value "\abc\asd", the function will be called.
will it be feasible given that it will probable end up with 2500 functions? i am wondering if this is the best way to do it.. please advise, thank you!
additional info (edited on 12 Oct)
hi, i am trying to compare lines in a text file and if the line matches one of my predefined text, i want to execute a batch/cscript command. is this possible?
what i have currently:
for /f "delims=" %%a in (input.txt) do (
set /a c+=1
set myVariable=%%a
REM if this line contains my predefined string A, execute a cscript command A
if not x%myVariable:prefinedtext1%==x%myVariable% echo theCommandIWantToExecute
REM if this line contains my predefined string B, execute a cscript command B
if not x%myVariable:prefinedtext2%==x%myVariable% echo theSecondCommandIWantToExecute
Yes this can be done, and quite easily for a few functions. But it will be a pain to maintain, and performance may suffer with ~2500 functions.
Here is a trivial demonstration with your sample data.
#echo off
for /f "delims=" %%C in (mylist.txt) do call :%%C
echo Done
exit /b
:\\abc\asd 123 home
echo Function 1 (%0) arg1=%1 arg2=%2
exit /b
:\\def\as 456 office
echo Function 2 (%0) arg1=%1 arg2=%2
exit /b
:\\ghi\as 789 elsewhere
echo Function 3 (%0) arg1=%1 arg2=%2
exit /b
--OUTPUT---
Function 1 (:\\abc\asd) arg1=123 arg2=home
Function 2 (:\\def\as) arg1=456 arg2=office
Function 3 (:\\ghi\as) arg1=789 arg2=elsewhere
Done
If the first value of each row represents a path to a batch script, then you can remove the : from the CALL, and then each batch script will be called. Your main script would then be tiny, and would perform better. But that is a lot of batch scripts to keep track of.
#echo off
for /f "delims=" %%C in (mylist.txt) do call %%C
echo Done
exit /b

Can someone tell me, why this batch script isn't working?

#echo off
:start
SET /A number=%RANDOM% * 3 / 32768 + 1
echo %number%>number.txt
PING localhost -n 2 >NUL
goto start
It should generate a random number from 1-3. And it does. But the .txt file is just empty and in the console, I get the message: "Echo is turned off".
Can someone help me?
>number.txt echo %number%
A digit directly before a redirector redirects a logical device (0=stdin, 1=stdout, 2=stderr, others unassigned). The position of the redirection instruction is generally irrelevant; only at the end of the command by convention and historical usage.

Batch to copy specific text from multiple files into one file based on a map

I have 15 input files and a map that says which input file should each output line come from. The input files all look the same:
1,some numbers
2,some numbers
...
2000,some numbers
The map file looks like
1, filename1
2, filename1
3, filename7
...
2000, filename4
I want to create one output file that consists of 2000 lines which were copied from the input files based on the map i.e. output lines 1 and 2 were copied from filename1, line 3 was copied from filename3, ... and line 2000 was copied from filename4.
Can you please help me figure out how to use the map?
I think my code should be something like
for i = 1 to 2000
currentInputFileName = (read i-th line from the map
to figure out input file name)
findstr "%i," /b %currentInputFileName% > %outputFile%
next i
Thanks for any help
Your approach is correct, but you have a couple minor errors: the number of line must be taken from the first token in the lines in map.txt file, and the filename is the second token. You could use your same code, but in such a case you must eliminate line numbers from map.txt file. Otherwise, you may eliminate the counter variable from the code and the space between the number and the filename in map.txt file.
Besides, you use a couple constructs that are particularly slow:
call subroutine is slow. Is better to place the subroutine code inside the for and use Delayed Expansion to get the variables.
The append redirection >> is slow because the output file is open and closed each time that a line is appended to it. It is much faster a normal > redirection.
This code should run much faster than the original; it uses the original format in map.txt file: 1,filename1, etc.
#echo off
(FOR /f "tokens=1,2 delims=," %%G IN (map.txt) DO (
findstr /b "%%G," "%%H"
)) > output.txt
I ended up writing it like this
#echo off
SET count=1
FOR /f %%G IN (map.txt) DO (call :subroutine "%%G")
GOTO :eof
:subroutine
findstr /b "%count%," %1 >> output.txt
set /a count+=1
GOTO :eof
Not sure if this is optimal in terms of speed. My input files actually contain not 2000 lines but 2000 blocks, each block 120 lines
1,1,some numbers
1,2,some numbers
...
1,120,some numbers
...
2000,120,some numbers
Is there a way to write this code to run faster?

For statement echoing DO ( commands ) in console when batch script runs

Basically when I am running this script, after runprog.exe returns (echos in cmd prompt) everytihng in the do ( ) section.
#echo off
set NODES=(server1.com server2.com)
for %%i in %NODES% do (
echo Log stuff... >> logfile.txt
runprog.exe /switch %%i
if %ERRORLEVEL%==0 (echo success) else (echo fail)
sleep 5
)
Edit: #echo off is at the top of the script.
The problem is in this sleep 5 command: it is a custom batch file that you have.
The funny thing is that if I run your batch file on my computer the exact same thing is happening, and I most probably have a different 'sleep' batch file than you. Mine contains the following:
#echo off
ping -n %1 127.0.0.1 > NUL 2>&1
Replacing sleep 5 with call sleep 5 fixes the problem here.
I have no idea why. Ask Microsoft.
As Mike Nakis said, it's the batch file sleep.
It's not important if sleep.bat contains #echo off or not.
The problem is that starting a batch file from another batch file transfers the control to the new batch file but doesn't return to the caller.
But in your case you have a FOR-loop which is completly cached by the cmd.exe.
That's the cause why the first batch doesn't stops immediately.
But when the second loop runs, the cmd.exe has leaved the batch-file-mode and is now in the cmd-line-mode.
You could control this by adding an echo line.
#echo off
set "world=" -- unset the world variable
for /L %%n in (1 1 3) do #(
call echo Hello %%n %%world%%
sleep.bat 1
)
The output will be
1 Hello
2 Hello %world%
3 Hello %world%
That's because the cmd-line-mode doesn't remove percent expansions when the variable is unset.
The CALL sleep.bat solves the problem, as then control simply returns to the caller, as expected.

Resources