Batch - Run functions in the same file async from each other function - multithreading

I have one single Batch file with 2 functions in it:
1.) MAIN
2.) ASYNC
Now i try to call the ASYNC function out of the MAIN function without waiting for the completion of the ASYNCfunction. Is that possible?
Here is my Batch file:
#echo off
:MAIN
setlocal
echo Here i am in the Main Thread
start /b :ASYNC
echo Here i am in the Main Thread again
endlocal
exit /b 0
:ASYNC
setlocal
echo I am in the ASYNC Thread
timeout /T 100
endlocal
exit /b 0
Is there any possibility to run a function in a single batchfile asynchron from another function in the same batchfile without separating the functions to multiple files?
Greets & Thank you :D

Yes, there is a possibility: use start to let the script restart itself, provide the label of the sub-routine as an argument and use goto rather than call to continue execution at that point:
#echo off
if not "%~1"=="" goto %~1
:MAIN
setlocal
echo Here I am in the MAIN thread
start "" /B cmd /D /C "%~f0" :ASYNC
echo Here I am in the MAIN thread again
endlocal
exit /b 0
:ASYNC
setlocal
echo Now I am in the ASYNC thread
timeout /T 10
endlocal
exit /b 0
When you run the script and want to first execute the main section, you must not provide an argument. If you do, it will be interpreted as a jump label. To avoid that, you could check whether the (first) argument begins with a : and skip the goto if not. Replace the line if not "%~1"=="" goto %~1 by the following to achieve that:
set "ARG1=%~1" & if not defined ARG1 shift /1 & goto :MAIN
if "%ARG1:~,1%"==":" goto %ARG1%
This is not absolutely safe against any odd arguments (like "&"&), but it will serve well in most situations. However, regard that the argument positions may not be as expected, because of the additional label argument (check out the argument string %*, which is even not going to be affected by shift).
Note, that the sub-routine then becomes executed in a new cmd.exe instance, so any environment changes will not reach the main instance.
There is even a better way to accomplish what you want, without affecting any potential arguments, namely to embed the label of the sub-routine in the script path itself when restarting the script (technique courtesy of user jeb, see his answer to How to pipe the final result of a windows batch for loop into another command):
#echo off
for /F "tokens=3 delims=:" %%Z in ("%~0") do goto :%%Z
:MAIN
setlocal
echo Here I am in the MAIN thread
start "" /B cmd /D /C "%~d0\:ASYNC:\..%~pnx0" %*
echo Here I am in the MAIN thread again
endlocal
exit /b 0
:ASYNC
setlocal
echo Now I am in the ASYNC thread
timeout /T 10
endlocal
exit /b 0
The key portion is the augmented path string %~d0\:ASYNC:\..%~pnx0, which is going to be resolved to %~d0%~pnx0 (that is the full script path %~0).
The sub-routine becomes again executed in a new cmd.exe instance.

Related

Replace %%20 in string using windows batch script

I have a use case where I want to replace %%20 which is part of a string for example: "Calculation%%20One". I want to replace this with "Calculation One".
This where I am stuck:
#echo off
setlocal enableextensions disabledelayedexpansion
>"temp" (
echo !Option1!
echo !Option2!
echo !Option3!
)
set "pattern=%%20"
for /f "usebackq delims=" %%a in ("temp") do (
echo data: %%a
set "line=%%a"
setlocal enabledelayedexpansion
if "!line:%pattern%=!"=="!line!" (
set string=!Option1!
set string2=%!string1!:%%20= %
) else (
set string2=%%a
)
endlocal
)
del /q tempFile
Can someone please help me with this? I have a program which is a combination of batch and python.
Thanks
It is unclear for me why the options are written into a temporary file for processing the values of the environment variables Option1, Option2 and Option3. And it would have been good to see the lines which define the environment variables Option1, Option2 and Option3 for the real values assigned to them.
So I suggest here a batch file which replaces %20 as found for example in HTML files or emails by a space character in all Option environment variables.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Option1=Calculation%%20One"
set "Option2=Calculation %%%%20Two!"
set "Option3=Any other string"
cls
echo The options before processing:
echo/
set Option
for /F "delims==" %%I in ('set Option 2^>nul') do call :ProcessOption "%%I"
echo/
echo The options after processing:
echo/
set Option
echo/
endlocal
pause
goto :EOF
:ProcessOption
setlocal EnableDelayedExpansion
set "ModifiedOption=!%~1:%%20= !"
endlocal & set "%~1=%ModifiedOption%"
goto :EOF
It is necessary to use delayed expansion on replacing all occurrences of %20 by a space character because otherwise Windows command interpreter would not know where the environment variable reference with string substitution ends. Replacing a string with percent sign is not possible using immediate expansion for that reason.
The command set Option outputs alphabetically sorted all environment variables starting case-insensitive with the string Option in format variable=value as it can be seen twice on running this batch file.
FOR executes this command with using a separate command process started in background and captures all lines written by command SET to handle STDOUT.
The string 2^>nul is executed finally as 2>nul and redirects the error message output by command SET to handle STDERR to the device NUL to suppress it. SET would output an error message in case of no environment variable starting with Option is defined in current environment. This error condition does not occur with this batch file. Read the Microsoft article about Using Command Redirection Operators. The redirection operator > must be escaped here with ^ to be interpreted first as literal character when Windows command interpreter processes the entire FOR command line before executing the command FOR which executes cmd.exe /c set Option 2>nul in background.
FOR processes the captured output of set Option line by line and splits each line up into substrings (tokens) with using the equal sign as delimiter as specified with delims==. The string left to first equal sign on each line is assigned to loop variable I. This is the name of the environment variable, i.e. Option1, Option2 and Option3 for this batch file.
With each OptionX environment variable name the subroutine ProcessOption is called for replacing all %20 in its value by a space character.
Here is a solution for environment variables with one or more exclamation marks in variable name.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "!Option1!=Calculation%%%%20One"
set "!Option2!=City%%20Country"
set "!Option3!=State%%%%20Country"
set "!Option4!=Any other address/string"
cls
echo The options before processing:
echo/
set !Option
for /F "delims==" %%I in ('set !Option 2^>nul') do call :ProcessOption "%%I"
echo/
echo The options after processing:
echo/
set !Option
echo/
endlocal
pause
goto :EOF
:ProcessOption
call set "ModifiedOption=%%%~1%%"
setlocal EnableDelayedExpansion
set "ModifiedOption=!ModifiedOption:%%%%20= !"
set "ModifiedOption=!ModifiedOption:%%20= !"
endlocal & set "ModifiedOption=%ModifiedOption%"
set "%~1=%ModifiedOption%"
set "ModifiedOption="
goto :EOF
This batch code replaces %20 AND %%20 in all environment variables starting with !Option in name by a space character in comparison to above replacing just %20 by a space in environment variables beginning with Option in name.
It is of course a bad idea to use characters in variable names which have a special meaning for Windows command interpreter like the characters &()[]{}^=;!'+,`~|<>%. It is possible as demonstrated above, but it is definitely not a good idea.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cls /?
echo /?
endlocal /?
for /?
goto /?
set /?
setlocal /?
See also answer on Single line with multiple commands using Windows batch file for an explanation of & operator.
And read DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ why it is better to use echo/ instead of echo. to output an empty line.

Batch File Calling Node.js - How to Set ERRORLEVEL From Node

I've got a batch file that calls a node program:
#echo off
echo Starting Deploy.js: %date% %time%
echo CurrentDir: %CD%
node .deploy/deploy.js
IF %ERRORLEVEL% NEQ 0 goto error
echo Finished Deploy.js: %date% %time%
echo %~n0: Completed %date% %time%
goto end
:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul
:exitSetErrorLevel
exit /b 1
:exitFromFunction
()
:end
endlocal
I'd like to be able to have my node.js program be able to have it hit the error condition on failure of the application.
How do I trigger that in node.js?
I tried having my main function return 0 or 1, but it's not automatically setting the ERRORLEVEL.
What is the proper way to do this?
Check node.js documentation about process object .In your case you'll not need a callback function so you can simply use:
process.exit(666);
where you can set your desired exit code instead of 666

Batch Move based on filename without Delimiters, String Only

Okay, Windows 7 Enterprise x64 here with a Windows batch file question. I am a somewhat basic user with little knowledge of batch file creation. I've modified existing scripts I've found online to my use, that is about it.
I have a piece of software that dumps it's output to a folder with file names concatenated from the project title, current system date, current system time, and project settings.
It will export two files in this format every time the project is saved:
PROJECTTITLE_2016_10_07__09_45_11__A_B_C.iges
PROJECTTITLE_2016_10_07__09_45_11__A_B_C.step
The A, B, and C representing switches used in the software that are specific to the project. These may exist or may not exist as in the file name can be _R_F or _R_F_Z etc.
"PROJECTTITLE" can literally be anything. This is where my problem arises using delimiters. You could potentially have file names like all of the following (using real examples from users):
11475shacklebody_2016_10_07__09_45_11__R_F.iges
11475shacklebody_2016_10_07__09_45_11__R_F.step
test_EFMflow_2016_10_07__09_45_11__R_Z.iges
test_EFMflow_2016_10_07__09_45_11__R_Z.step
untitled16_2016_10_07__09_45_11__R.iges
untitled16_2016_10_07__09_45_11__R.step
#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.iges
#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.step
prooftestwithoutupperlandsimproved-4_2016_10_07__09_45_11.iges
prooftestwithoutupperlandsimproved-4_2016_10_07__09_45_11.step
What I want to do is move both the IGES and STEP files from the output folder on the C drive to a new folder on a networked drive with name based on "PROJECTTITLE," creating that folder if needed. I have already task scheduled a -delim based batch to run every night, but found delimiters to not be sufficient for my use.
While it seems like an easy job to do with delimiters, looking for the first underscore, I have had projects with underscores in their names that screws up the folder naming. Since delimiters only work for individual characters, not strings, I have been looking for examples of batch files I can adapt to my use with no luck finding any similar to what I want to do that do not use delimiters.
It seems simple, search for string "_2016," in filename, and take all characters before "_2016" and create a new directory, placing files containing those characters in that folder. I am lost as to how to do this without delimiters though.
What I have working so far, using delimiters looking for underscores, creating folders and moving to those folders on a mapped drive:
for /f "delims=_" %%V in ('dir /b /a-d C:\Output\*_*.iges') do (
mkdir "I:\ENG\PARTS\%%V" 2>nul
move "C:\Output\%%V_*.iges" "I:\ENG\PARTS\%%V" >NUL 2>nul
move "C:\Output\%%V_*.step" "I:\ENG\PARTS\%%V" >NUL 2>nul
)
It is a very simple batch file for what it does, but falls flat on it's face with titles containing underscores.
A few things:
Searching for _2016 would mean the batch file would need yearly maintenance. Could we either search for system %YEAR% or somehow search for "_####_##_##_" with something like a regular expression to get away from searching for system date or a specific year?
EDIT:
While not ideal as the switches are useful, I found a way in the software to not export the project specific switches at the end of the file name. So now the export would be:
PROJECTTITLE_2016_10_07__09_45_11.iges
PROJECTTITLE_2016_10_07__09_45_11.step
Which I know I can trim from right, what, 21 characters, use that name to make a folder and search the directory for all files containing that trimmed string.
It still would be nice to figure out how to search for the specific string though with the switches intact. I am willing to learn, so throw all explanations of your code you can at me.
Double (Late) EDIT:
First, thank you all for answering this, I deeply appreciate your help.
Double underscores in the the filename are quite rare, but do happen, probably due to typos. It becomes more of an issue with the volume of files I'm planning to move with this. The software runs on maybe 100 user machines with 20 or so being heavy users, each saving up to maybe 1000 files a day. The software will automatically save in increments, as the user runs the simulation. I'm trying to give them a way to collaborate and view each other's simulation results over the network (that we actively encourage them to use) and it figures that the software is hard coded to output to the C drive (for "performance" as the vendor tells me). I'm looking into scheduling the files to move every 15 minutes on every PC in their OU instead of nightly to give a near-real-time view on what they are working on.
Another option I explored was symbolically linking the output folder on each machine to the software's folder network drive, but found that this really doesn't solve the user's "organization" issue, putting like project runs in the same folder. This also has the issue of not allowing them to save a project out of the office without VPN, which some users do do, then move their files over when they get back in the office.
Thank you for your assistance.
Next batch script should do the job even if a file name contains cmd poisonous characters like space or % percent sign etc.
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_fouts=C:\Output" your setting
set "_fouts=D:\test\39924063" my setting
for /F %%G in ('wmic OS get localdatetime ^|find "."') do set "_fyear=%%G"
pushd "%_fouts%"
set "_fyear=%_fyear:~0,4%"
call :doDir
set /A _fyear -= 1
call :doDir
popd
ENDLOCAL
goto :eof
:doDir
rem debugging output echo(%_fyear%
for /f "delims=" %%V in ('
dir /b /a-d "*_%_fyear%_*.iges" "*_%_fyear%_*.step" 2^>NUL') do (
set "_fname=%%~nV" filename without extesion
set "_fexte=%%~xV" extesion only
call :doAll
)
goto :eof
:doAll
call set "_ftail=%%_fname:*_%_fyear%_=%%"
call set "_fproj=%%_fname:_%_fyear%_%_ftail%=%%"
rem debugging output echo("%_fproj%" "%_fname%" "%_fexte%"
ECHO mkdir "I:\ENG\PARTS\%_fproj%" 2>nul
ECHO move "%_fname%%_fexte%" "I:\ENG\PARTS\%_fproj%\"
goto :eof
Output (note that operational mkdir and move commands are merely displayed for debugging purposes using ECHO mkdir and ECHO move, respectively):
==> dir /B /S "D:\test\39924063" /S
D:\test\39924063\#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.iges
D:\test\39924063\#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.step
D:\test\39924063\%PROJECT TITLE_2016_10_07__09_45_11__A_B_C.iges
D:\test\39924063\%PROJECT TITLE_2016_10_07__09_45_11__A_B_C.step
==> D:\bat\SO\39924063.bat
mkdir "I:\ENG\PARTS\#14drop_wire-edm"
move "#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.iges" "I:\ENG\PARTS\#14drop_wire-edm\"
mkdir "I:\ENG\PARTS\%PROJECT TITLE"
move "%PROJECT TITLE_2016_10_07__09_45_11__A_B_C.iges" "I:\ENG\PARTS\%PROJECT TITLE\"
mkdir "I:\ENG\PARTS\#14drop_wire-edm"
move "#14drop_wire-edm_2016_10_07__09_45_11__R_F_Z.step" "I:\ENG\PARTS\#14drop_wire-edm\"
mkdir "I:\ENG\PARTS\%PROJECT TITLE"
move "%PROJECT TITLE_2016_10_07__09_45_11__A_B_C.step" "I:\ENG\PARTS\%PROJECT TITLE\"
==>
Resources (required reading, incomplete):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~nV, %~xV etc. special page) Command Line arguments (Parameters)
(set "_fyear=%_fyear:~0,4%" etc.) Extract part of a variable (substring)
(%variable:StrToFind=NewStr% etc.) Variable Edit/Replace
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
REM (
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*__*" '
) DO (
IF /i "%%~xa"==".iges" CALL :process "%%a"
IF /i "%%~xa"==".step" CALL :process "%%a"
)
REM )>"%outfile%"
GOTO :EOF
:: Process filename "%1"
:process
SET "fullname=%~1"
SET "junk=%fullname:*__=%"
CALL SET "project=%%fullname:%junk%=%%"
SET "project=%project:~0,-13%
ECHO(MD "%destdir%\%project%"
ECHO(MOVE "%sourcedir%\%~1" "%destdir%\%project%\"
GOTO :eof
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
This approach simply performs a directory list without directorynames (/a-d) of each file in the source directory that contains a double-underscore. Each filename matching is assigned to %%a and if the extension part (%%~xa) is one of the targets, then process the filename.
Processing consists of removing all of the characters before the double-underscore and then removing that junk part from the full name, giving project+date. Remove the last 13 characters and you have your project name.
Will have problems with any filename containing certain symbols like % or = but should be fine with underscores.
This version assumes there will not be an instance of _YYYY_ in the PROJECTTITLE.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
(Set OutDir=I:\ENG\PARTS)
(Set SrcDir=C:\Output)
If Not Exist "%SrcDir%\" Exit/B 1
If Not Exist "%OutDir%\" Exit/B 1
For /F "EOL=Y" %%A In ('WMIC Path Win32_LocalTime Get Year') Do (
For /F "Delims=" %%B In ("%%A") Do Set "ThisYr=%%B")
For /F "Delims=" %%A In ('Where "%SrcDir%:*_%ThisYr%_*.iges"') Do (
If Exist "%%~dpnA.step" Call :Sub %%~nA)
Exit/B
:Sub
Set "BigTit=%~1"
For /F "Delims=" %%A In ('CMD /Q /C "Call Echo %%BigTit:_%ThisYr%_=&:%%"') Do (
If Not Exist "%OutDir%\%%A\" MD "%OutDir%\%%A"
Move "%SrcDir%\%~1*.*" "%OutDir%\%%A">Nul)
Edit, there is no need to export without the potentially useful project switches using the above code.
Supposing the PROJECTTITLE part of the file names does not contain two consecutive underscores, you could use the following script, which splits off the first occurrence of __ and everything after (so the time part and the optional switches are removed), using a standard for loop rather than for /F; then it splits off another 11 characters (hence the remaining date part), using sub-string expansion:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=."
set "_TARGET=."
for /F delims^=^ eol^= %%F in ('
pushd "%_SOURCE%" ^&^& ^(
dir /B /A:-D ^
"*_????_??_??__??_??_??*.iges" ^
"*_????_??_??__??_??_??*.step" ^
^& popd^)
') do (
call :PROCESS "%%F"
)
endlocal
exit /B
:PROCESS val_file
setlocal DisableDelayedExpansion
set "FILE=%~1"
setlocal EnableDelayedExpansion
for %%I in ("!FILE:__=";"!") do (
endlocal
set "ITEM=%%~I"
setlocal EnableDelayedExpansion
goto :NEXT
)
:NEXT
if defined ITEM (
set "ITEM=!ITEM:~,-11!"
md "%_TARGET%\!ITEM!" 2> nul
if not exist "%_TARGET%\!ITEM!\!FILE!" (
move /Y "%_SOURCE%\!FILE!" "%_TARGET%\!ITEM!\" > nul
)
)
endlocal
endlocal
exit /B
Finally I come up with a script that is able to handle even files whose PROJECTTITLE part contain __ on their own. It splits off the last occurrence of __ and everything after (so the optional switches are removed, if any, or the time part is removed otherwise), using a standard for loop rather than for /F; then it splits off another 21 characters (hence the remaining date and time parts), or, if no optional switches were present, just another 11 characters (hence the remaining date part), using sub-string expansion:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=."
set "_TARGET=."
for /F delims^=^ eol^= %%F in ('
pushd "%_SOURCE%" ^&^& ^(
dir /B /A:-D ^
"*_????_??_??__??_??_??*.iges" ^
"*_????_??_??__??_??_??*.step" ^
^& popd^)
') do (
call :PROCESS "%%F"
)
endlocal
exit /B
:PROCESS val_file
setlocal DisableDelayedExpansion
set "FILE=%~1"
set "BASE=%~n1"
set "NAME=" & set "ITEM="
setlocal EnableDelayedExpansion
for %%I in ("!BASE:__=";"!") do (
for /F "delims=" %%E in ("!NAME!!ITEM!__") do (
endlocal
set "NAME=%%E"
set "ITEM=%%~I"
setlocal EnableDelayedExpansion
)
)
if defined NAME (
set "NAME=!NAME:~2,-2!"
echo("!ITEM!"| > nul findstr /R "^\"[0-9][0-9]_[0-9][0-9]_[0-9][0-9]\"$" || (
if defined NAME set "NAME=!NAME:~,-10!"
)
if defined NAME set "NAME=!NAME:~,-11!"
if defined NAME (
md "%_TARGET%\!NAME!" 2> nul
if not exist "%_TARGET%\!NAME!\!FILE!" (
move /Y "%_SOURCE%\!FILE!" "%_TARGET%\!NAME!\" > nul
)
)
)
endlocal
endlocal
exit /B

BATCH - Find string in text file and add a new string after that line

I'm trying to search a text file for a particular string from a bat file. If the string exist, add a new string after it on the next line. I can't seem to get the code below working correctly. Any Ideas?
This is the string i'm searching for in my text file. [/Script/MyGame.Mode]
Here's what the text file looks like.
[/Script/Config.Mode]
Something here 1
Something here 2
[/Script/MyGame.Mode]
Something here 1
Something here 2
[/Script/Edit.Mode]
Something here 1
Something here 2
And here's how I want it to look.
[/Script/Config.Mode]
Something here 1
Something here 2
[/Script/MyGame.Mode]
RedirectReferences=(PackageName="%Package%",PackageURLProtocol="%PackageURLProtocol%",PackageURL="%WebAddress%/%Package%%Ext%",PackageChecksum="")
Something here 1
Something here 2
[/Script/Edit.Mode]
Something here 1
Something here 2
Here's the code I have so far.
#echo off
:GETINFO
echo.
echo.
cls
echo.
echo Let's get some information for your config.
echo Note: The information you enter below is case sensitive. You can copy and paste.
echo.
echo Here's a Package Name example: "DM-MyTest-WindowsNoEditor"
echo.
set /p Package=Enter Package Name:
echo.
echo.
echo.
echo The Package URL Protocol will be "http" or "https"
echo.
set /p PackageURLProtocol=Enter Package URL Protocol:
echo.
echo.
echo.
echo Here's a WebAddress example: "www.myredirect.com/test" (Don't add the trailing /)
set /p WebAddress=Enter Redirect(WebAddress)URL:
echo.
echo.
echo.
echo The file extention is usually ".pak"
echo.
set /p Ext=Enter Map File Extention:
echo.
cls
echo.
echo Please wait... Currently Creating Test References.
:SHOWLINE
echo.
set NewURL=RedirectReferences=(PackageName="%Package%",PackageURLProtocol="%PackageURLProtocol%",PackageURL="%WebAddress%/%Package%%Ext%",PackageChecksum=""^^)
pause
:WRITENEW
set inputfile=game.txt
set outputfile=game.temp.txt
(for /f usebackq^ delims^=^ eol^= %%a in ("%inputfile%") do (
if "%%~a"=="[/Script/MyGame.Mode]" call echo %NewURL%
echo %%a
))>>"%outputfile%"
echo.
pause
When I run the posted code in Command Prompt console I see a syntax error:
) was unexpected at this time.
Apparently the parentheses inside NewURL break things when expanded in the loop.
A straightforward solution would be to delay the expansion by using the call trick:
call echo %%NewURL%%
Alternatively:
setlocal enableDelayedExpansion & echo !NewURL! & endlocal
Or double-escape the closing parenthesis with ^^ (one time for set and another for an expanded value inside the loop):
set NewURL=.............PackageChecksum=""^^)
Another issue is that the output file name is the same as the input file name but it's impossible to redirect output into the same file as you're reading.
Change the output name to a different file. Then replace the original after the loop is finished:
set inputfile=game.txt
set outputfile=game.temp.txt
...................
))>>"%outputfile%"
move/y "%outputfile%" "%inputfile%"
And to change the order of the new string to print it after the found line simply swap the two lines inside the inner loop:
echo %%a
if "%%~a"=="[/Script/MyGame.Mode]" call echo %%NewURL%%

How to run batch script without using *.bat extension

Is there any method in Windows through which we can execute a batch script without *.bat extension?
This is an interesting topic to me! I want to do some observations about it.
The important point first: A Batch file is a file with .BAT or .CMD extension. Period. Batch files can achieve, besides the execution of usual DOS commands, certain specific Batch-file facilities, in particular:
Access to Batch file parameters via %1 %2 ... and execution of SHIFT command.
Execution of GOTO command.
Execution of CALL :NAME command (internal subroutine).
Execution of SETLOCAL/ENDLOCAL commands.
Now the funny part: Any file can be redirected as input for CMD.exe so the DOS commands contained in it are executed in a similar way of a Batch file, with some differences. The most important one is that previous Batch-file facilities will NOT work. Another differences are illustrated in the NOT-Batch file below (I called it BATCH.TXT):
#echo off
rem Echo off just suppress echoing of the prompt and each loop of FOR command
rem but it does NOT suppress the listing of these commands!
rem Pause command does NOT pause, because it takes the character that follows it
pause
X
rem This behavior allows to put data for a SET /P command after it
set /P var=Enter data:
This is the data for previous command!
echo Data read: "%var%"
rem Complex FOR/IF commands may be assembled and they execute in the usual way:
for /L %i in (1,1,5) do (
set /P line=
if "!line:~0,6!" equ "SHOW: " echo Line read: !line:~6!
)
NOSHOW: First line read
SHOW: Second line
NOSHOW: This is third line
SHOW: The line number 4
NOSHOW: Final line, number five
rem You may suppress the tracing of the execution redirecting CMD output to NUL
rem In this case, redirect output to STDERR to display messages in the screen
echo This is a message redirected to STDERR >&2
rem GOTO command doesn't work:
goto label
goto :EOF
rem but both EXIT and EXIT /B commands works:
exit /B
:label
echo Never reach this point...
To execute previous file, type: CMD /V:ON < BATCH.TXT
The /V switch is needed to enable delayed expansion.
More specialized differences are related to the fact that commands in the NOT-Batch file are executed in the command-line context, NOT the Batch-file context. Perhaps Dave or jeb could elaborate on this point.
EDIT: Additional observations (batch2.txt):
#echo off
rem You may force SET /P command to read the line from keyboard instead of
rem from following lines by redirecting its input to CON device.
rem You may also use CON device to force commands output to console (screen),
rem this is easier to write and read than >&2
echo Standard input/output operations> CON
echo/> CON
< CON set /P var=Enter value: > CON
echo/> CON
echo The value read is: "%var%"> CON
Execute previous file this way: CMD < BATCH2.TXT > NUL
EDIT: More additional observations (batch3.txt)
#echo off
rem Dynamic access to variables that usually requires DelayedExpansion via "call" trick
rem Read the next four lines; "next" means placed after the FOR command
rem (this may be used to simulate a Unix "here doc")
for /L %i in (1,1,4) do (
set /P line[%i]=
)
Line one of immediate data
This is second line
The third one
And the fourth and last one...
(
echo Show the elements of the array read:
echo/
for /L %i in (1,1,4) do call echo Line %i- %line[%i]%
) > CON
Execute this file in the usual way: CMD < BATCH3.TXT > NUL
Interesting! Isn't it?
EDIT: Now, GOTO and CALL commands may be simulated in the NotBatch.txt file!!! See this post.
Antonio
Just use:
type mybat.txt | cmd
Breaking it down...
type mybat.txt reads mybat.txt as a text file and prints the contents. The | says capture anything getting printed by the command on its left and pass it as an input to the command on its right. Then cmd (as you can probably guess) interprets any input it receives as commands and executes them.
In case you were wondering... you can replace cmd with bash to run on Linux.
in my case, to make windows run files without extension (only for *.cmd, *.exe) observed, i have missed pathext variable (in system varailbles) to include .cmd. Once added i have no more to run file.cmd than simply file.
environment variables --> add/edit system variable to include .cmd;.exe (ofcourse your file should be in path)
It could be possible yes, but probably nor in an easy way =) cause first of all.. security.
I try to do the same thing some year ago, and some month ago, but i found no solution about it.. you could try to do
execu.cmd
type toLaunch.txt >> bin.cmd
call bin.cmd
pause > nul
exit
then in toLaunch.txt put
#echo off
echo Hello!
pause > nul
exit
just as example, it will "compile" the code, then it will execute the "output" file, that is just "parse"
instead of parsed you could also just rename use and maybe put an auto rename inside the script using inside toLaunch.txt
ren %0 %0.txt
hope it helped!
It is possible at some degree. You'll need an admin permissions to run assoc and ftype commands. Also a 'caller' script that will use your code:
Lets say the extension you want is called .scr.
Then execute this script as admin:
#echo off
:: requires Admin permissions
:: allows a files with .scr (in this case ) extension to act like .bat/.cmd files.
:: Will create a 'caller.bat' associated with the extension
:: which will create a temp .bat file on each call (you can consider this as cheating)
:: and will call it.
:: Have on mind that the %0 argument will be lost.
rem :: "installing" a caller.
if not exist "c:\scrCaller.bat" (
echo #echo off
echo copy "%%~nx1" "%%temp%%\%%~nx1.bat" /Y ^>nul
echo "%%temp%%\%%~nx1.bat" %%*
) > c:\scrCaller.bat
rem :: associating file extension
assoc .scr=scrfile
ftype scrfile=c:\scrCaller "%%1" %%*
You even will be able to use GOTO and CALL and the other tricks you know. The only limitation is that the the %0 argument will be lost ,tough it can be hardcoded while creating the temp file.
As a lot of languages compile an .exe file for example I think this a legit approach.
If you want variables to be exported to the calling batch file, you could use
for /F "tokens=*" %%g in (file.txt) do (%%g)
This metod has several limitations (don't use :: for comments), but its perfect for configuration files.
Example:
rem Filename: "foo.conf"
rem
set option1=true
set option2=false
set option3=true
#echo off
for /F "tokens=*" %%g in (foo.conf) do (%%g)
echo %option1%
echo %option2%
echo %option3%
pause

Resources