Skip to content
shellmap

pasteMerge lines from multiple files side-by-side with a delimiter across all 5 shells

Equivalents in every shell

Bashunix
paste a.txt b.txt

Joins 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.

Zshunix
paste a.txt b.txt

Same external binary. Zsh process substitution helps for pipelines: `paste <(cmd1) <(cmd2)`.

Fishunix
paste a.txt b.txt

Same external binary. Fish process substitution uses `psub`: `paste (cmd1 | psub) (cmd2 | psub)`.

PowerShellwindows
$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).

cmd.exewindows
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)

Bash
paste -d , a.txt b.txt
Fish
paste -d , a.txt b.txt
PowerShell
$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

Bash
paste -sd " " numbers.txt
Fish
paste -sd " " numbers.txt
PowerShell
(Get-Content numbers.txt) -join " "

Sum a column of integers (paste -sd+ + bc)

Bash
paste -sd+ numbers.txt | bc
Fish
paste -sd+ numbers.txt | bc
PowerShell
(Get-Content numbers.txt | Measure-Object -Sum).Sum

Gotchas

  • `-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.

WSL & PowerShell Core notes

pwshNo native pwsh `paste`. The array-index loop is the cross-OS pattern and works identically on every pwsh OS. For pure 2-file merging, `[Linq.Enumerable]::Zip` is the type-safe option but verbose. For N-file paste behaviour, the loop scales naturally — just stack more `$($files[$i][$_])` references.
WSLWSL `paste` is GNU coreutils. Useful when joining a Windows-side text file with a Linux-side log: `paste /mnt/c/Users/.../windows.txt linux.txt` works inside WSL. Watch for CRLF on Windows-saved files — pre-process with `tr -d "\r"` if columns appear shifted by trailing carriage returns.

Related commands