Batch Script - Find and replace text in multiple files in a directory without asking user to install any program or add other files to my batch script

喜欢而已 提交于 2019-12-25 18:16:31

问题


I need batch file that searches for a text (eg., FOO) and replaces it with another text (eg., BAR) in all the text files within a folder and it's sub-folders.

I need to give this batch file to the user. So, it is not possible to ask the user to install anything else and also i don't wanna add other files to my batch script, is that even passable? I found many answer for this issue but everyone advise to install other program or to add a file to the batch script . Can someone please help me with this?


回答1:


Here is a simple and pure batch-file solution -- let us call it replac.bat:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=%~3"   & rem // (path to root directory; third command line argument)
set "_MASK=%~4"   & rem // (file search pattern; fourth command line argument)
set "_SEARCH=%~1" & rem // (search string; first command line argument)
set "_REPLAC=%~2" & rem // (replace string; second command line argument)
set "_CASE=#"     & rem // (clear for case-insensitive search)
set "_RECURS=#"   & rem // (clear for non-recursive search)
set "_TMPF=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (path to temporary file)

rem // Validate passed command line arguments, apply defaults:
if not defined _SEARCH exit /B 1
if not defined _ROOT set "_ROOT=."
if not defined _MASK set "_MASK=*.txt"

rem // Prepare `if` option (case-insensitivity) for later use:
if defined _CASE (set "IFSW=") else (set "IFSW=/I")
rem // Prepare `for` option (recursion) for later use:
if defined _RECURS (set "FOROPT=/R") else (set "FOROPT=")
rem // Change into root directory temporarily:
pushd "%_ROOT%" || exit /B 1
rem // Loop through all matching files in the directory tree:
for %FOROPT% %%F in ("%_MASK%") do (
    rem // Write to temporary file:
    > "%_TMPF%" (
        set "FLAG="
        rem /* Read current file line by line; use `findstr` to precede every line by
        rem    its line number and a colon `:`; this way empty lines appear non-empty
        rem    to `for /F`, which avoids them to be ignored; otherwise empty lines
        rem    became lost: */
        for /F "delims=" %%L in ('findstr /N "^" "%%~fF"') do (
            rem // Store current line text:
            set "LINE=%%L"
            setlocal EnableDelayedExpansion
            rem // Remove line number prefix:
            set "LINE=!LINE:*:=!"
            rem // Skip replacement for empty line text:
            if defined LINE (
                rem /* Use `for /F` loop to avoid trouble in case search or replace
                rem    strings contain quotation marks `"`: */
                for /F "tokens=1* delims== eol==" %%I in ("!_SEARCH!=!_REPLAC!") do (
                    rem // Query to handle case-sensitivity:
                    if %IFSW% "!LINE!"=="!LINE:%%I=%%I!" (
                        rem // Detect whether replacement changes line:
                        if not "!LINE!"=="!LINE:%%I=%%J!" (
                            rem // Actually do the sub-string replacement:
                            set "LINE=!LINE:%%I=%%J!"
                            set "FLAG=#"
                        )
                    )
                )
            )
            rem // Output the resulting line text:
            echo(!LINE!
            if defined FLAG (endlocal & set "FLAG=#") else (endlocal)
        )
    )
    rem // Check whether file content would change upon replacement:
    if defined FLAG (
        rem // Move the temporary file onto the original one:
        > nul move /Y "%_TMPF%" "%%~fF"
    ) else (
        rem // Simply delete temporary file:
        del "%_TMPF%"
    )
)
popd

endlocal
exit /B

To use this script, provide the search string as the first and the replace string as the second command line argument, respectively; the third argument defines the root directory which defaults to the current working directory, and the fourth one defines the file pattern which defaults to *.txt:

replac.bat "Foo" "Bar"

The following restrictions apply:

  • all matching files must be plain ASCII/ANSI text files with Windows-style line-breaks;
  • neither the lines in the files nor the search and replace strings may be longer than approximately 8190 bytes/characters;
  • the search string must not be empty, it must not begin with * or ~, and it must not contain =;
  • the replace string must not begin with =;
  • the search and replace strings must not contain ! or ^;



回答2:


for /r %i in (bar.txt) do echo ren "%i" foobar.txt

Remove the echo ONLY once you are sure the files are going to be correctly renamed.

to use it in a Batch file, add additional % to the variables, like:

@echo off
for /r %%i in (bar.txt) do echo ren "%%i" foobar.txt


来源:https://stackoverflow.com/questions/46467475/batch-script-find-and-replace-text-in-multiple-files-in-a-directory-without-as

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!