If you want a pure batch solution, then the simplest thing to do is to encapsulate the code in a subroutine that takes the name of the file as an argument, and call that routine from within a FOR loop that iterates the file names. This is a general approach that can be used for any code that you want to run iteratively
against files in a folder.
The end result of your code does not create or rename any folders, so a simple FOR is safe to use. But if your code creates or renames folders, then a FOR loop could also process the newly created or renamed files. This can be solved by using FOR /F with the DIR /B command instead.
Note - I eliminated dead (unused) variables from the code.
@echo off
setlocal enabledelayedexpansion
pushd "c:\path\to\your\folder\containing\files\to\modify"
for %%F in (*.txt) do call :replace "%%F"
exit /b
:replace
set INTEXTFILE=%1
set OUTTEXTFILE=test_out.txt
set SEARCHTEXT=Cat
set REPLACETEXT=Dog
for /f "tokens=1,* delims=¶" %%A in ( '"findstr /n ^^ %INTEXTFILE%"') do (
SET string=%%A
for /f "delims=: tokens=1,*" %%a in ("!string!") do set "string=%%b"
if "!string!" == "" (
echo.>>%OUTTEXTFILE%
) else (
SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%!
echo !modified! >> %OUTTEXTFILE%
)
)
del %INTEXTFILE%
rename %OUTTEXTFILE% %INTEXTFILE%
exit /b
But there are many limitations and inefficiencies with the code, with lots of room for improvement.
Limitations:
Input and output lines must be a bit less than 8191 bytes long.
The search ignores case
The search string cannot contain =
or begin with ~
, *
or !
The replace string cannot contain !
Lines containing !
will be corrupted because delayed expansion is enabled when %%A
is expanded. This can be solved by strategically toggling delayed expansion on and off within the loop(s).
Leading :
will be stripped from all lines because consecutive delimiter characters are treated as a single delimiter.
The replacement will be corrupted if the search term contains %%a
or %%b
or %%A
. This can be avoided by transferring the search and replacement terms to FOR variables.
Certain characters within the search and/or replacement terms could cause problems or require complex escape sequences. This can be simplified by getting the desired strings in environment variables (which may still require escape sequences) and then using delayed expansion and FOR /F to transfer the values to FOR variables.
There are obscure situations where ECHO.
can fail. The only safe variant that is guaranteed to work is ECHO(
.
A non empty line could become empty after replacement if the replacement string is empty, and the empty line will not be output properly because neither ECHO.
nor ECHO(
was used.
Inefficiencies / other issues
Redirection is performed for each line of output, which is slow. Better (faster) to redirect once outside the loop.
The DEL/RENAME pair can be replaced by a single MOVE command
CALL is relatively slow. Best to minimize use of CALL if you want the fastest possible solution. But sometimes it cannot be avoided.
I prefer to have my temp file name to be a derivative of the original name. I typically append a .new
extension to the original name, so "original.txt" becomes "original.txt.new"
Below is highly optimized code that addresses all but the first 4 points above. It is about as robust and efficient as pure batch can get if you want to use FOR /F to read the file.
@echo off
setlocal disableDelayedExpansion
pushd "c:\path\to\your\folder\containing\files\to\modify"
set "find=Cat"
set "repl=Dog"
setlocal enableDelayedExpansion
for /f delims^=^ eol^= %%S in ("!find!") do (
for /f delims^=^ eol^= %%R in ("!repl!") do (
endlocal
for %%F in (*.txt) do (
for /f "delims=" %%L in ('findstr /n "^" "%%F"') do (
set "ln=%%L"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
if defined ln set "ln=!ln:%%S=%%R!"
echo(!ln!
endlocal
)
) >"%%F.new" & move /y "%%F.new" "%%F" >nul
)
)
popd
The above required a lot of experience and arcane knowledge to develop. Even after all the work, it still has the following limitations.
Input and output lines must be a bit less than 8191 bytes long.
The search ignores case
The search string cannot contain =
or begin with ~
, *
or !
The replace string cannot contain !
Removing those limitations would require a ridiculous amount of slow and even more impenetrable code. Hardly worth it.
That is why I have abandoned using pure batch for text processing, and I developed JREPL.BAT to provide powerful regular expression text processing capabilities to the Windows command environment. JREPL is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.
JREPL makes the solution so simple, it can easily be run directly on the command line, without any batch file.
pushd "c:\your\path\with\files\to\be\modified"
for %F in (*.txt) do call jrepl "Cat" "Dog" /l /f "%F" /o -
popd
The search is case sensitive. You can add the /i
option if you want the search to ignore case. Change the %F
to %%F
if you use the command within a batch script.