paste — Merge lines from multiple files side-by-side with a delimiter across all 5 shells
Equivalents in every shell
paste a.txt b.txtJoins line N of `a.txt` with line N of `b.txt`, tab-separated. `-d ","` changes the delimiter. `-s` flips axis: writes each file's lines as ONE row joined by the delimiter (i.e. transpose). Common idiom: `paste -sd+ numbers.txt | bc` to sum a column.
paste a.txt b.txtSame external binary. Zsh process substitution helps for pipelines: `paste <(cmd1) <(cmd2)`.
paste a.txt b.txtSame external binary. Fish process substitution uses `psub`: `paste (cmd1 | psub) (cmd2 | psub)`.
$a = Get-Content a.txt; $b = Get-Content b.txt; 0..($a.Count-1) | ForEach-Object { "$($a[$_])`t$($b[$_])" }No native `paste`. The idiom indexes both arrays in parallel. `[System.Linq.Enumerable]::Zip` is the .NET equivalent but only handles TWO collections — paste's N-file arity needs an explicit loop. For uneven-length files, pwsh produces empty entries (vs paste's empty cells).
powershell -Command "$a=gc a.txt;$b=gc b.txt;0..($a.Count-1)|%{\"$($a[$_])`t$($b[$_])\"}"No native cmd equivalent — shell out to pwsh. The above one-liner does the same as the pwsh entry, but escape rules are brutal: backticks need doubling, `%` needs escaping, double quotes need backslash-escaping.
Worked examples
Merge two files line-by-line with comma delimiter (CSV-ish)
paste -d , a.txt b.txtpaste -d , a.txt b.txt$a=gc a.txt;$b=gc b.txt;0..($a.Count-1)|ForEach-Object{"$($a[$_]),$($b[$_])"}Transpose a column of numbers into a single space-separated row
paste -sd " " numbers.txtpaste -sd " " numbers.txt(Get-Content numbers.txt) -join " "Sum a column of integers (paste -sd+ + bc)
paste -sd+ numbers.txt | bcpaste -sd+ numbers.txt | bc(Get-Content numbers.txt | Measure-Object -Sum).SumGotchas
- `-d` accepts a RING of delimiters: `paste -d ",;|" a b c d` cycles `,;|,` between successive column joins. Useful for CSV-with-mixed-separators, but unexpected if you assumed `-d` was a single fixed char — `paste -d "ab"` does NOT make `ab` the delimiter, it alternates `a` then `b`.
- Uneven-length files: `paste` pads short files with empty strings (so output preserves alignment). The pwsh array-indexing idiom produces `$null` (rendered as empty), which usually but not always matches paste's behaviour — test on real inputs.
- `-s` (serial) means "consume one file fully before moving to the next" — semantically a TRANSPOSE when you have a one-column input: `paste -s file.txt` puts all lines on one row. The `-s` and `-d` combination is the bash one-liner for "join column into row with custom separator".
- pwsh `[System.Linq.Enumerable]::Zip` is THE .NET equivalent but it's limited to TWO sources and requires an explicit selector lambda — `[Linq.Enumerable]::Zip[string,string,string]($a, $b, [Func[string,string,string]]{ param($x,$y) "$x`t$y" })`. Most pwsh users just write the loop.
- paste reads ALL input files in parallel — concatenating with `cat a.txt b.txt | paste -` does NOT do what you want (joins each line with itself). Use `paste - -` (with as many `-` placeholders as columns) for stdin-as-N-streams, or explicit file args.