0

I want to combine all the txt files having a header in a folder. I need the header to be written only once.

s1.txt

Header
1
2
3
4
5
6
7
8

s2.txt

Header
12
22
32
42
52
62
72
82

s3.txt

Header
123
223
323
423
523
623
723
823

There are two solutions

1: Simple one

copy /b *.txt Combined.txt // It writes header each time also

2: solution with loop

@echo off
for %%f in (*.txt) do (
   if not exist Combined.txt (
      copy "%%f" Combined.txt
   ) else (
      for /F  "usebackq skip=1 delims=" %%a in ("%%f") do (
         echo %%a>> Combined.txt
      )
   )
)

But it is not working properly.

Header
1
2
3
4
5
6
7
812  // NEED to start with next line
22
32
42
52
62
72
82
123
223
323
423
523
623
723
823

Any idea?? Also other solutions???

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Shahgee
  • 3,303
  • 8
  • 49
  • 81

2 Answers2

3

A quite simple solution is to use the find command since this appends a final line-break when needed, so you do not have to particularly take care of that on your own:

@echo off
rem /* Use a flag-style variable that indicates the first file,
rem    so we know whether or not we have to apply the header: */
set "FIRST=#"
rem // Write to the output file:
> "Combined.txt" (
    rem /* Loop through all input files, with the order is defined by the file system
    rem    (the used pattern also ensures to does not match the output file): */
    for %%I in ("s*.txt") do (
        rem // Query the flag-style variable:
        if defined FIRST (
            rem // This is the first input file, hence return the whole content:
            < "%%~I" find /V ""
        ) else (
            rem // This is not the first input file, hence exclude the header:
            < "%%~I" find /V "Header"
        )
        rem // Clear the flag-style variable here:
        set "FIRST="
    )
)

If the header string (Header) may occur within other lines but the headline also, try to replace the command line < "%%~I" find /V "Header" by the one < "%%~I" (set /P ="" & findstr "^"), although this might cause problems on certain Windows versions as findstr might hang (refer to the post What are the undocumented features and limitations of the Windows FINDSTR command?).


Here is an approach based on for /F loops; the difference to your similar approach is that also the first file is handled by a for /F loop, which lets also the last line be terminated by a line-break in the output:

@echo off
rem /* Use a flag-style variable that indicates the first file,
rem    so we know whether or not we have to apply the header: */
set "FIRST=#"
rem // Write to the output file:
> "Combined.txt" (
    rem /* Loop through all input files, with the order is defined by the file system
    rem    (the used pattern also ensures to does not match the output file): */
    for %%I in ("s*.txt") do (
        rem // Query the flag-style variable:
        if defined FIRST (
            rem // This is the first input file, hence return the whole content:
            for /F "usebackq delims=" %%L in ("%%~I") do (
                echo(%%L
            )
        ) else (
            rem // This is not the first input file, hence exclude the header:
            for /F "usebackq skip=1 delims=" %%L in ("%%~I") do (
                echo(%%L
            )
        )
        rem // Clear the flag-style variable here:
        set "FIRST="
    )
)

Note that a for /F skips blank lines.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
0

This code assumes that the header is in the first file mentioned. If you are on a supported Windows machine, PowerShell will be available. This may require the current PowerShell 5.1 or higher.

=== Get-CombinedFile.ps1

$outFilename = 'C:/src/t/Combined.txt'
$files = @('./s1.txt', './s2.txt', './s3.txt')

Set-Location -Path 'C:/src/t'
Get-Content -Path $files[0] -First 1 |
    Out-File -FilePath $outFilename -Encoding ascii
Get-ChildItem -Path $files |
    ForEach-Object {
        Get-Content -Path $_ |
            Select-Object -Skip 1 |
            Out-File -FilePath $outFilename -Encoding ascii -Append
    }

Invoke it in a cmd.exe shell or .bat file script.

powershell -NoLogo -NoProfile -File 'C:\src\t\Get-CombinedFile.ps1'
lit
  • 14,456
  • 10
  • 65
  • 119