You're simply writing the content of the two files one after the other instead of processing corresponding lines.
PowerShell has no built-in way for enumerating collections by positionally corresponding elements,[1] but you can use .NET APIs:
# IMPORTANT:
# Since .NET's working dir. usually differs from PowerShell's, it
# is important to always use FULL PATHS when calling .NET methods.
# The calls to Convert-Path ensure that.
# Get enumerators for the lines of both files.
$fileA = [System.IO.File]::ReadLines((Convert-Path 1.txt))
$fileB = [System.IO.File]::ReadLines((Convert-Path 2.txt))
# Iterate over the files' lines in tandem, and write each pair
# to the output file.
& {
while ($fileA.MoveNext(), $fileB.MoveNext() -contains $true) {
'{0}:{1}' -f $fileA.Current, $fileB.Current
}
} | Set-Content joinedFile.txt
This solution is memory-friendly, as it reads the lines lazily, i.e., on demand, using the System.IO.File.ReadLines
method, obviating the need to read the files into memory as a whole.
If one of the files "runs out lines", an empty string is used in lieu of a value.
If you want to limit processing to only as many lines as the two files have in common, replace the while
condition with:
while ($fileA.MoveNext(), $fileB.MoveNext() -notcontains $false)
Alternatively, use a LINQ-based solution, as shown next.
LINQ-based solutions:
Important: The solutions below use the System.Linq.Enumerable.Zip
method, which assumes that the the input collections have the same number of elements. If they differ in element count, processing is invariably limited to as many elements as the smaller collection has, i.e. to how many elements they have in common.
# Get enumerators for the lines of both files.
$fileA = [System.IO.File]::ReadLines((Convert-Path 1.txt))
$fileB = [System.IO.File]::ReadLines((Convert-Path 2.txt))
[Linq.Enumerable]::Zip(
$fileA,
$fileB,
[Func[string, string, string]] { '{0}:{1}' -f $args[0], $args[1] }
) | Set-Content joinedFile.txt
- Simpler alternative that reads both files in full first:
[Linq.Enumerable]::Zip(
(Get-Content -ReadCount 0 1.txt),
(Get-Content -ReadCount 0 2.txt),
[Func[object, object, string]] { '{0}:{1}' -f $args[0], $args[1] }
) | Set-Content joinedFile.txt
[1] A proposal to introduce such a feature, in the form of foreach ($elementFromA, $elementFromB in $collectionA, $collectionB) { ... }
, was rejected, unfortunately - see GitHub issue #14732.