1

I am trying to make a program to make a file that echoes the contents of a file into a new one. For example:

If I had a file named foo.txt with the contents of:

@echo off
echo Hello World
pause
exit

The file would create a separate one that has the contents of:

@echo off
color a> foo2.txt
echo @echo off>> foo2.txt
echo echo Hello World>> foo2.txt
echo pause>> foo2.txt
echo exit>> foo2.txt

However, I have come across a problem. If I add an exclamation mark to the file:

@echo off
echo Hello World!
pause
exit

It would not include the exclamation mark in the file.

How would I go about fixing this?

My Code:

@echo off
setlocal enabledelayedexpansion
:input
set /p "input=Input Filename: "
if not exist "%input%" goto input
cls
set /p "output=Output Filename: "
cls
echo @echo off> "%input%-Echo.bat"
echo color a^> "%output%">> "%input%-Echo.bat"
for /f "usebackq delims=" %%A in ("%input%") do (
    set "line=%%A"
    set "line=!line:^=^^!"
    set "line=!line:<=^<!"
    set "line=!line:>=^>!"
    set "line=!line:&=^&!"
    set "line=!line:|=^|!"
    set "line=!line:(=^(!"
    set "line=!line:)=^)!"
    set "line=!line:%%=%%%%!"
    echo(echo !line! ^>^> "%output%" >> "%input%-Echo.bat"
)
echo The process has been completed. The file is called "%input%-Echo.bat"
echo.
<nul set /p=Press any key to exit . . . 
pause>nul
exit
John Davis
  • 27
  • 6
  • Change the line ```setlocal enabledelayedexpansion``` to ```setlocal enableextensions disabledelayedexpansion```. Then add a new line ```setlocal enabledelayedexpansion``` on the line after ```set "line=%%A"```. Now add a new line ```endlocal``` on the line after ```echo(echo !line! ^>^> "%output%" >> "%input%-Echo.bat"```. – Compo Jul 29 '23 at 14:17
  • Nice, that works! However, so that I can become more experienced, could you please explain how it works or provide me a link for the syntax of these commands? Thanks! – John Davis Jul 29 '23 at 14:24

1 Answers1

0

The following batch file solves the problem with the incorrect processing of lines with an exclamation mark by enabling delayed variable expansion after assignment of the line read from the file to the environment variable Line. The improved code handles also correct empty lines and does not remove them.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls

:PromptInputFile
set "InputFile="
set /P "InputFile=Input file name: " || goto PromptInputFile
set "InputFile=%InputFile:"=%"
if not defined InputFile goto PromptInputFile
if not exist "%InputFile%" goto PromptInputFile
if exist "%InputFile%\" goto PromptInputFile
cls

:PromptOutputFile
set "OutputFile="
set /P "OutputFile=Output file name: " || goto PromptOutputFile
set "OutputFile=%OutputFile:"=%"
if not defined OutputFile goto PromptOutputFile
if exist "%OutputFile%\" goto PromptOutputFile
cls

for %%I in ("%InputFile%") do set "BatchFileFull=%%~dpnI-Echo.cmd" & set "BatchFileName=%%~nI-Echo.cmd"

(echo @echo off
echo echo @color a^>"%OutputFile%"
for /F "delims=" %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%InputFile%" 2^>nul') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    set "Line=!Line:*:=!"
    if defined Line (
        set "Line=!Line:^=^^!"
        set "Line=!Line:<=^<!"
        set "Line=!Line:>=^>!"
        set "Line=!Line:&=^&!"
        set "Line=!Line:|=^|!"
        set "Line=!Line:(=^(!"
        set "Line=!Line:)=^)!"
        set "Line=!Line:%%=%%%%!"
        echo(echo !Line! ^>^>"!OutputFile!"
    ) else echo echo(^>^>"!OutputFile!"
    endlocal
))>"%BatchFileFull%"
echo The process has been completed. The file is called: "%BatchFileName%"
echo(

set /P "=Press any key to exit . . . "<nul
pause>nul

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • cls /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • set /?
  • setlocal /?

See also:

Some additional notes:

  1. The command exit without its option /B is nearly never needed at end of a batch file and is just counterproductive if a user runs a batch file from within a command prompt window instead of double clicking on a batch file in a file manager like Windows File Explorer or Total Commander. It is also counterproductive on debugging a batch file during its development. The exception is a batch file which is used for an installation process started from a GUI installer executable on which the batch file deletes itself with the last command line.

  2. The usage of >> results in cmd.exe opening the output file on already existing and seeking to end of the file or creating the file on not existing, appending the text and closing the file. It is very inefficient to do that for each line to write into a file. It can even result in output file does not contain all lines because of an anti-virus application opens the output file for scanning for malicious code between cmd.exe closes the file and opens it again for appending the next line which the anti-virus application prevents. The batch code above opens the file referenced with %BatchFileFull% just once with overwriting a perhaps already existing file with same name, appends all text output by any command ECHO used in the command block beginning with ( and ending with ) and finally closes the file. It is possible that this fails if there is already such a file with read-only attribute set or the user does not have the necessary permissions to create and write that file or there is a directory with same name as the file to create (very unlikely) or the file to create exists already and is opened by another application which prevents opening it by cmd.exe.

  3. It is completely unclear what is the purpose of this batch file. It makes absolutely no sense to create a batch file which reads a batch file and creates another batch file which produces by chance (not guaranteed by code design) the original batch file with an additional command line added at top and with the difference of a trailing space at end of each command line in comparison to original batch file.

  4. The batch file does not do correct the escaping of the characters with a special meaning for the Windows Command Processor. The characters ^<>&|() are interpreted literally by cmd.exe on being inside a double quoted argument string.
    A command line like

    %SystemRoot%\System32\findstr.exe /I /R "^Error" %SystemRoot%\*.log
    

    in the input file becomes

    echo %%SystemRoot%%\System32\findstr.exe /I /R "^^Error" %%SystemRoot%%\*.log >>"ListErrors.cmd"
    

    in the *-Echo.cmd file producing an output file ListErrors.cmd with

    %SystemRoot%\System32\findstr.exe /I /R "^^Error" %SystemRoot%\*.log 
    

    and the regular expression does not find anymore lines beginning case-insensitive with Error in all .log files in the Windows directory as the command line in the input file because of ^^ instead of just ^ in the search expression.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Thanks for the useful information! I will use it in the future. As of the use of this file, I cannot say. I already know the basic functions of the commands that you have listed for me. Thank you for all of the helpful sources! – John Davis Jul 30 '23 at 00:19