简体   繁体   中英

Replace String with Batch for multiple files

I'm trying to use the script that was suggested here .

My goal is to be able to reuse the script for multiple files. I have one file that contains this script and another one that simply triggers the script multiple times with different parameters.

ReplaceString.bat

@echo off
REM -- Prepare the Command Processor --
SETLOCAL ENABLEEXTENSIONS
SETLOCAL DISABLEDELAYEDEXPANSION

::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
:$changed 20100115
:$source http://www.dostips.com
if "%~1"=="" findstr "^::" "%~f0"&GOTO:EOF
for /f "tokens=1,* delims=]" %%A in ('"type %3|find /n /v """') do (
    set "line=%%B"
    if defined line (
        call set "line=echo.%%line:%~1=%~2%%"
        for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) ELSE echo.
)

And let's say:

foo.bat

set oldString=foo
set newString=newFoo

ReplaceString.bat %oldString% %newString% someFile.txt >someFile.txt

ReplaceString.bat %oldString% %newString% someFile2.txt >someFile2.txt

But for whatever reason, the execution stops after successfully running the first call.

I tried to call the ReplaceString.bat with START & CALL , tried not to redirect the output to a file, but each time I ended up having the same result.

I would like to be able either forcing foo.bat to continue to run, or ReplaceString.bat not to exit.

Edit: I mistakenly assumed the script was ending prematurely, but what was actually happening is, I just wasn't receiving an output to my console, the commands did run with CALL command. The other problem with my script was redirecting the output back to the input file, which was fixed by redirecting output to a temporary file and replacing it with the original once the call ended.

That ReplaceString.bat works however you use it in problematic way in foo.bat ; you should change it as follows:

set oldString=foo
set newString=newFoo

CALL ReplaceString.bat %oldString% %newString% someFile.txt  >someFileX.txt

CALL ReplaceString.bat %oldString% %newString% someFile2.txt >someFile2X.txt
  1. Note that ˙CALL˙ command call s one batch program from another:

CALL a second batch file
The CALL command will launch a new batch file context along with any specified parameters. When the end of the second batch file is reached (or if EXIT is used), control will return to just after the initial CALL statement .

Arguments can be passed either as a simple string or using a variable.

  1. Note that if you redirect the ReplaceString.bat output to the same file which is to be parsed as in ReplaceString.bat %oldString% %newString% someFile.txt >someFile.txt , then the redirection operator > will empty the output file first so that called script has nothing to parse (or parses an empty file )… Use different input and output files as shown in code sample above.

First, I suggest to change ReplaceString.bat to:

@echo off
rem -- Prepare the Command Processor --
setlocal EnableExtensions DisableDelayedExpansion

::BatchSubstitude - parses a File line by line and replaces a substring"
::syntax: BatchSubstitude.bat OldStr NewStr File
::          OldStr [in] - string to be replaced
::          NewStr [in] - string to replace with
::          File   [in] - file to be parsed
:$changed 20100115
:$source http://www.dostips.com
if "%~1"=="" %SystemRoot%\System32\findstr.exe "^::" "%~f0" & goto :EOF
for /f "tokens=1,* delims=]" %%A in ('"type %3|%SystemRoot%\System32\find.exe /n /v """') do (
    set "line=%%B"
    if defined line (
        call set "line=echo.%%line:%~1=%~2%%"
        for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) else echo.
)
endlocal

Each usage of setlocal results in creating a copy of entire environment table with pushing a pointer to previous environment table on stack, pushing current state of command extensions and current state of delayed expansion on stack and pushing also current directory path on stack. It is possible to enable command extensions (by default enabled) and disable delayed expansion (by default disabled) with just one setlocal .

Windows command processor restores the environment as it was on starting a batch file on reaching exit point on a batch file processing. But it is nevertheless a good idea to use for every setlocal the corresponding endlocal command.

It is also good to call findstr and find with full path and file extension as it can easily happen that in environment variable PATH there is a folder path included before %SystemRoot%\\System32 which contains also a find.exe or findstr.exe ported from Unix to Windows, but of course working different, or a find.bat , or a findstr with a file extension defined in environment variable PATHEXT .

But the main reason why second line with ReplaceString.bat is never called on processing foo.bat is:

The first line with ReplaceString.bat is without command call .

Therefore processing of foo.bat continues with ReplaceString.bat with never coming back to foo.bat as not calling the other batch file.

The following lines are needed for foo.bat :

set oldString=foo
set newString=newFoo

call ReplaceString.bat %oldString% %newString% someFile.txt >someFile_1.txt
move /Y someFile_1.txt someFile.txt

call ReplaceString.bat %oldString% %newString% someFile2.txt >someFile_2.txt
move /Y someFile_2.txt someFile2.txt

For more details see my answer on How to call a batch file in the parent folder of current batch file?

And it is not possible to redirect the output to input file. The output must be redirected to a separate file which is next moved over the input file.

One more note:

ReplaceString.bat works for many, but not for all file contents.

For example running above just slightly improved version of ReplaceString.bat with

ReplaceString.bat dostips mytips ReplaceString.bat >ReplaceString.txt

results in the unexpected error message

The system cannot find the path specified.

and the file ReplaceString.txt has dostips replaced by mytips in line 11 as expected, but ^ is missing on line 12, and line 13 from batch file is missing completely in the output text file.

For alternatives see How can you find and replace text in a file using the Windows command-line environment?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM