batch-filecopyappendfilemerge

Issue when merging 2 files into one file in batch


I have an issue when merging 2 files into one file. The first file contains the lines 1 2 3 4 and the second contains the lines 5 6 7.

When I do this: copy test1.txt+test2.txt result.txt I get the below lines. Please see that 4 is near 5.

1
2
3
45
6
7

I don't know why, I expect that 5 6 7 to continue from a new line like:

1
2
3
4
5
6
7

This is a test case. I want to extend this on larger files. I tried also "type" and the same result.

Could someone advise please? Thanks


Solution

  • As stated in Mofi's comment, the last line of test1.txt does not end with a newline. Neither COPY nor TYPE append a newline to the end of the file, so the end of test1 runs into the begining of test2.

    In your comment you state you solved the problem using:

    for %%x in (test*.txt) do more "%%x" >>new.txt
    

    That can be made a bit more efficient by using:

    (for %%x in (test*.txt) do more "%%x") >new.txt
    

    Either way, the above works fine as long as the content does not contain tab characters, and none of the source files exceed 32k lines.

    Tab characters will be converted into a series of space characters by MORE.

    And MORE with redirected output will pause, waiting for input, if it reaches 32k lines.

    If either of the above are a problem, then you can do something like:

    (
      for %%x in (test*.txt) do (
        type "%%x"
        echo(
      )
    ) >new.txt
    

    That will always insert a newline between each file. But that could be a problem if the last line of a file already contains the newline. In such a case you would end up with

    1
    2
    3
    4
    
    5
    6
    7
    

    A perfect solution requires that you detect when the last line of a file is not terminated with a newline.

    The following works if you know that all the files use Windows style newlines (carriage return/line feed). The FINDSTR identifies lines that do not contain a carriage return.

    (
      for %%x in (test*.txt) do (
        type "%%x"
        findstr /v $ "%%x" >nul && echo(
      )
    ) >new.txt
    

    If some files use 'nix style instead (newline only), then a solution is a bit more complicated. This FINDSTR identifies lines that do not contain a line feed.

    setlocal enableDelayedExpansion
    :: define LF to contain a line feed character (0x0A)
    set ^"LF=
    
    ^" The empty line above is critical - DO NOT REMOVE
    (
      for %%x in (test*.txt) do (
        type "%%x"
        findstr /v "!lf!." >nul && echo(
      )
    ) >new.txt