0

I want to nest a for loop inside a batch file to delete carriage return. I tried it like you can see below but it does not work.

@echo off
setLocal EnableDelayedExpansion

for /f "tokens=* delims= " %%a in (Listfile.txt) do (
    set /a N+=1
    set v!N!=%%a
)

for /l %%i in (1, 1, %N%) do (
    echo !v%%i!
    for /r "tokens=* delims=" %%i in (windows.cpp) do (
        echo %%i >> Linux11.cpp
    )
)
pause

Here I want to check with windows.cpp. If its working I like to change windows .cpp with !v%%i!

2
  • The last (inner) for syntax is wrong: there is the switch /r stated but there is an option string provided ("tokens=* delims=") as expected if using switch /f... Commented Nov 27, 2015 at 0:12
  • To convert end-of-line markers (or line-breaks) between platforms you may want to check out this answer... Commented Apr 8, 2020 at 16:17

3 Answers 3

7

You cannot do this in a batch file. You have no way of addressing or writing arbitrary characters. Every tool on Windows normally makes sure to output Windows line breaks (i.e. CR+LF). Some can read Unix-style line breaks just fine, which is why you can easily convert from them. But to them isn't possible.

Also as a word of caution: Source code files often contain blank lines (at least mine do) that are for readability. for /f skips empty lines which is why you're mangling the files for your human readers there. Please don't do that.

As for your question: When nesting two loops you have to make sure that they don't use the same loop variable. Show me a language where code like you wrote actually works.

Something like

for /l %%i in (1, 1, %N%) do ( 
  echo !v%%i! 
  for /f "tokens=* delims=" %%l in ("!v%%i!") do (   
    rem do whatever you want to do with the lines
  )
)

should probably work better (you missed the final closing parenthesis as well). Thing to remember: If you want to use a certain variable instead of a fixed file name it surely helps replacing that fixed file name by that variable.

Sign up to request clarification or add additional context in comments.

2 Comments

here in echo %%i >> Linux11.cpp i am getting the file name , its not copying the content in that *.cpp files in Listfile.txt
echo just writes a string to the screen ... what makes you think that it would actually do anything with a file's contents?
1

It would be probably easiest to use some unix2dos/dos2unix converter to do that or some win32 flavor of sed.

Comments

0

The intrinsic issue of your code is already addressed by another answer, hence I am going to focus on the main task you are trying to accomplish, namely converting DOS/Windows-style end-of-line markers (or line-breaks) to Unix-style ones.

Doing this is very tricky in a batch file, but give the following script a try. Supposing it is called convert.bat, and the original text file is named convert.txt, run the script using the following command line:

convert.bat "convert.txt" LF

The name of the returned file will get the original file name with _converted_EOL appended. The second argument LF specifies Unix-style line-breaks; omitting it will return DOS/Windows-style ones.

So here is the code:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem check whether or not an existing file is given as the first argument
>&2 (
    if "%~1"=="" (
        echo No file specified.
        exit /B 2
    ) else if not exist "%~1" (
        echo File "%~1" not found.
        exit /B 1
    )
)

rem get carriage-return character
for /F %%A in ('copy /Z "%~0" nul') do set "CR=%%A"

rem get line-feed character (the two empty lines afterwards are mandatory!)
(set ^"LF=^
%= blank line =%
^")

rem check which line-break is given by the second argument
rem (`CR` - carriage return (Mac); `LF` - line feed (Unix);
rem  anything else or nothing - CR+LF (Windows, default))
setlocal EnableDelayedexpansion
set "BR=!CR!!LF!"
if /I "%~2"=="CR" set "BR=!CR!" & (>&2 echo CR not supported.) & exit /B 3
if /I "%~2"=="LF" set "BR=!LF!"

rem convert line-breaks; append `_converted_EOL` to file name
setlocal DisableDelayedExpansion
> "%~n1_converted_EOL%~x1" (
    for /F delims^=^ eol^= %%L in ('
        findstr /N /R "^" "%~1"
    ') do (
        set "LINE=%%L"
        rem firstly, precede every line with a dummy character (`:`) and
        rem append the specified line-break in order to avoid the loss of
        rem leading white-spaces or trouble with leading equal-to signs,
        rem all caused by `set /P`, which is needed here to return the
        rem line without a trailing DOS/Windows-style line-break (opposed
        rem to `echo`); then, let `pause` strip off that character;
        rem lastly, let `findstr` return the remainder;
        rem (the `rem` suffix is just there to fix syntax highlighting)
        cmd /V /C ^< nul set /P #="!LINE:*:=:!!BR!" | (> nul pause & findstr "^") & rem/ "^"
    )
)
endlocal
endlocal

endlocal
exit /B

The following restrictions apply:

  • no line must be longer than about 8190 characters (this is a general limitation of batch files);
  • the file must not contain any null-bytes (well, a normal text file should not hold such, but Unicode-encoded do);
  • the last line of the returned file will always be terminated by a line-break, even if the respective original line is not;

And here is another solution for line-break conversions: Convert all CR to CRLF in text file using CMD

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.