How create combined file from two text files in powershell?

433 views Asked by At

How can I create file with combined lines from two different text files and create new file like this one:

First line from text file A
First line from text file B
Second line from text file A
Second line from text file B
...
2

There are 2 answers

1
Civette On BEST ANSWER
$file1content = Get-Content -Path "IN_1.txt"
$file2content = Get-Content -Path "IN_2.txt"

$filesLenght =@($file1content.Length, $file2content.Length)

for ($i = 1; $i -le ($filesLenght | Measure-Object -Maximum).Maximum; $i++)
{   Add-Content -Path "OUT.txt" $file1content[$i]
    Add-Content -Path "OUT.txt" $file2content[$i]
}
0
mklement0 On

For a solution that:

  • keeps memory use constant (doesn't load the whole files into memory up front)
  • performs acceptably with larger files.

direct use of .NET APIs is needed:

# Input files, assumed to be in the current directory.
# Important: always use FULL paths when calling .nET methods.
$dir = $PWD.ProviderPath
$fileA = [System.IO.File]::ReadLines("dir/fileA.txt")
$fileB = [System.IO.File]::ReadLines("$dir/fileB.txt")

# Create the output file.
$fileOut = [System.IO.File]::CreateText("$dir/merged.txt")

# Iterate over the files' lines in tandem, and write each pair
# to the output file.
while ($fileA.MoveNext(), $fileB.MoveNext() -contains $true) {
  if ($null -ne $fileA.Current) { $fileOut.WriteLine($fileA.Current) }
  if ($null -ne $fileB.Current) { $fileOut.WriteLine($fileB.Current) }
}

# Dipose of (close) the files.
$fileA.Dispose(); $fileB.Dispose(); $fileOut.Dispose()

Note: .NET APIs use UTF-8 by default, but you can pass the desired encoding, if needed.

See also: The relevant .NET API help topics:


A solution that uses only PowerShell features:

  • Note: Using PowerShell-only features you can only lazily enumerate one file's lines at a time, so reading the other into memory in full is required. (However, you could again use a lazy enumerable via the .NET API, i.e. System.IO.File]::ReadLines() as shown above, or read both files into memory in full up front.)

  • The key to acceptable performance is to only have one Set-Content call (plus possibly one Add-Content call) which processes all output lines.

    • However, given that Get-Content (without -Raw) is quite slow itself, due to decorating each line read with additional properties, the solution based on .NET APIs will perform noticeably better.
# Read the 2nd file into an array of lines up front.
# Note: -ReadCount 0 greatly speeds up reading, by returning
#       the lines directly as a single array.
$fileBLines = Get-Content fileB.txt -ReadCount 0 

$i = 0 # Initialize the index into array $fileBLines.

# Lazily enumerate the lines of file A.
Get-Content fileA.txt | ForEach-Object {
  $_ # Output the line from file A.
  # If file B hasn't run out of lines yet, output the corresponding file B line.
  if ($i -lt $fileBLines.Count) { $fileBLines[$i++] }
} | Set-Content Merged.txt

# If file B still has lines left, append them now:
if ($i -lt $fileBLines.Count) {
  Add-Content Merged.txt -Value $fileBLines[$i..($fileBLines.Count-1)]
}

Note: Windows PowerShell's Set-Content cmdlet defaults to "ANSI" encoding, whereas PowerShell (Core) (v6+) uses BOM-less UTF-8; use the -Encoding parameter as needed.