简体   繁体   English

批处理脚本 - 在一个目录中的多个文件中查找和替换文本,而不要求用户安装任何程序或将其他文件添加到我的批处理脚本中

[英]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

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.我需要在文件夹及其子文件夹中的所有文本文件中搜索文本(例如 FOO)并将其替换为另一个文本(例如 BAR)的批处理文件。

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?有人可以帮我解决这个问题吗?

Here is a simple and pure solution -- let us call it replac.bat :这是一个简单而纯粹的解决方案——让我们称之为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=* delims=*= eol=~" %%K in ("!_SEARCH!=!_REPLAC!") do (
                    rem // Split search and replace strings:
                    for /F "tokens=1 delims== eol==" %%I in ("%%K") do (
                        rem // Query to handle case-sensitivity:
                        if %IFSW% "!LINE!"=="!LINE:%%I=%%I!" (
                            rem // Detect whether replacement changes line:
                            if not "!LINE!"=="!LINE:%%K!" (
                                rem // Actually do the sub-string replacement:
                                set "LINE=!LINE:%%K!"
                                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 :第三个参数定义默认为当前工作目录的根目录,第四个参数定义默认为*.txt的文件模式:

replac.bat "Foo" "Bar"

The following restrictions apply:以下限制适用:

  • all matching files must be plain ASCII/ANSI text files with Windows-style line-breaks;所有匹配的文件必须是带有 Windows 样式换行符的纯 ASCII/ANSI 文本文件;
  • neither the lines in the files nor the search and replace strings may be longer than approximately 8190 bytes/characters;文件中的行和搜索和替换字符串都不能超过大约 8190 个字节/字符;
  • the search string must not be empty, it must not begin with * or ~ , and it must not contain = ;搜索字符串不能为空,不能以*~开头,不能包含=
  • the search and replace strings must not contain !搜索和替换字符串不得包含! or ^ ;^ ;
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.只有在确定文件将被正确重命名后,才删除echo

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

Oops, sorry, I just saw that you want a solution without installing anything... This doesn't apply to OP then, but might be useful to someone else so I'll leave it up.哎呀,对不起,我刚刚看到你想要一个不安装任何东西的解决方案......这不适用于 OP,但可能对其他人有用,所以我会留下它。

If you install git bash (or mingw or cygwin etc) you can use sed , as explained in this answer: https://stackoverflow.com/a/11660023 .如果您安装 git bash(或 mingw 或 cygwin 等),您可以使用sed ,如本答案所述: https : //stackoverflow.com/a/11660023 Use globbing to match multiple files.使用通配符匹配多个文件。 eg例如

sed -i 's/FOO/BAR/g' ./*.txt

sed uses regexp, so you have access to powerful features like matching only the start of lines ( ^ ) or the end of lines ( $ ), any number ( [0-9] ) etc. sed使用正则表达式,因此您可以使用强大的功能,例如仅匹配行首 ( ^ ) 或行尾 ( $ )、任何数字 ( [0-9] ) 等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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