paste [OPTION]... [FILE]...
paste -s [OPTION]... [FILE]...
The paste command merges lines from multiple files side-by-side, separating them
with tabs (by default) or a custom delimiter. Think of it as the horizontal equivalent of
cat - while cat stacks files vertically (appending one after another), paste combines
them horizontally (joining corresponding lines across files).
This makes paste essential for data manipulation tasks: combining columns from different files,
creating CSV data from separate sources, reformatting structured text, and general column-oriented
data processing. The -s (serial) flag changes the behavior to merge all lines from
each file into a single line, useful for converting multi-line data into single-line comma-separated
or tab-separated values.
# Create sample files
cat > names.txt << 'EOF'
Alice
Bob
Charlie
David
EOF
cat > ages.txt << 'EOF'
25
30
35
40
EOF
cat > cities.txt << 'EOF'
NYC
LA
Chicago
Houston
EOF
# Basic paste - merge two files
paste names.txt ages.txt
# Merge three files
paste names.txt ages.txt cities.txt
# Paste with file viewing
echo "=== Names ==="
cat names.txt
echo "=== Ages ==="
cat ages.txt
echo "=== Combined ==="
paste names.txt ages.txt
# Two files:
Alice 25
Bob 30
Charlie 35
David 40
# Three files:
Alice 25 NYC
Bob 30 LA
Charlie 35 Chicago
David 40 Houston
# The tab character separates columns (shows as spaces in display)
By default, paste uses tab as delimiter. The output shown uses spaces for readability, but actual output has tab characters. Use paste -d',' for comma-separated output if needed.
# Comma-separated (CSV)
paste -d',' names.txt ages.txt cities.txt
# Pipe-delimited
paste -d'|' names.txt ages.txt cities.txt
# Space-delimited
paste -d' ' names.txt ages.txt cities.txt
# Colon-delimited (like /etc/passwd format)
paste -d':' names.txt ages.txt cities.txt
# Multiple character delimiter (uses first char)
paste -d', ' names.txt ages.txt cities.txt
# Special characters: newline in delimiter
paste -d$'\n' names.txt ages.txt
# Create a properly formatted CSV with headers
echo "Name,Age,City" > data.csv
paste -d',' names.txt ages.txt cities.txt >> data.csv
cat data.csv
# Format as a table with custom spacing
paste -d' | ' names.txt ages.txt cities.txt | \
awk '{printf "| %-10s | %-5s | %-10s |\n", $1, $3, $5}'
# Comma-separated:
Alice,25,NYC
Bob,30,LA
Charlie,35,Chicago
David,40,Houston
# Pipe-delimited:
Alice|25|NYC
Bob|30|LA
Charlie|35|Chicago
David|40|Houston
# Colon-delimited:
Alice:25:NYC
Bob:30:LA
Charlie:35:Chicago
David:40:Houston
# CSV file:
Name,Age,City
Alice,25,NYC
Bob,30,LA
Charlie,35,Chicago
David,40,Houston
# Formatted table:
| Alice | 25 | NYC |
| Bob | 30 | LA |
| Charlie | 35 | Chicago |
| David | 40 | Houston |
The -d option accepts a single character or a list of characters. With multiple characters, paste cycles through them for each column separator.
# Create a list file
cat > fruits.txt << 'EOF'
Apple
Banana
Cherry
Date
Elderberry
EOF
# Serial mode with default tab delimiter
paste -s fruits.txt
# Serial mode with comma delimiter
paste -s -d',' fruits.txt
# Serial mode with space delimiter
paste -s -d' ' fruits.txt
# Multiple files in serial mode
cat > vegetables.txt << 'EOF'
Carrot
Broccoli
Spinach
EOF
# Each file becomes one line
paste -s -d',' fruits.txt vegetables.txt
# Create a formatted list with "and"
paste -s -d',' fruits.txt | sed 's/,/, /g; s/\(.*\),/\1 and/'
# Convert a column to SQL IN clause
echo "SELECT * FROM products WHERE name IN ("
paste -s -d',' fruits.txt | sed "s/^/'/; s/$/'/; s/,/', '/g"
echo ");"
# Practical: get all unique values in one line
cat access.log | awk '{print $1}' | sort -u | paste -s -d','
# Default tab delimiter:
Apple Banana Cherry Date Elderberry
# Comma delimiter:
Apple,Banana,Cherry,Date,Elderberry
# Space delimiter:
Apple Banana Cherry Date Elderberry
# Multiple files (each file one line):
Apple,Banana,Cherry,Date,Elderberry
Carrot,Broccoli,Spinach
# Formatted with "and":
Apple, Banana, Cherry, Date and Elderberry
# SQL IN clause:
SELECT * FROM products WHERE name IN (
'Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'
);
The -s flag is perfect for converting vertical lists to horizontal format. Common use cases include creating SQL IN clauses, formatting comma-separated lists, and aggregating data for reports.
# Merge command output with a file
ls -1 /tmp | paste - ages.txt
# Use stdin multiple times
seq 1 5 | paste - -
# Combine file and command output
paste names.txt <(echo "Status"; tail -n +2 names.txt | sed 's/.*/Active/')
# Number lines from a file
cat names.txt | nl | paste - ages.txt
# Add line numbers to paste output
paste names.txt ages.txt | nl
# Merge three sources: file, command, file
paste names.txt <(date +%Y | xargs -n1) cities.txt
# Complex pipeline: merge sorted unique values
cat file1.txt file2.txt | sort -u | paste -s -d','
# Combine cut columns with paste
cut -f1 data.tsv | paste - <(cut -f3 data.tsv)
# Create a quick lookup table
echo "1 2 3 4 5" | tr ' ' '\n' | \
paste - <(echo "one two three four five" | tr ' ' '\n')
# ls with ages:
file1.txt 25
file2.txt 30
file3.txt 35
# seq with itself (two columns):
1 2
3 4
5
# File with status:
Alice Active
Bob Active
Charlie Active
David Active
# Numbered with ages:
1 Alice 25
2 Bob 30
3 Charlie 35
4 David 40
# Lookup table:
1 one
2 two
3 three
4 four
5 five
Using process substitution <(command) with paste is powerful - it treats command output as if it were a file. This allows complex data merging from multiple sources in a single pipeline.
# Create files of different lengths
cat > short.txt << 'EOF'
A
B
C
EOF
cat > medium.txt << 'EOF'
1
2
3
4
5
EOF
cat > long.txt << 'EOF'
X
Y
Z
W
Q
R
S
EOF
# Paste files of different lengths
paste short.txt medium.txt long.txt
# With comma delimiter to see empty fields clearly
paste -d',' short.txt medium.txt long.txt
# Identify where files end
paste -d'|' short.txt medium.txt long.txt | nl
# Fill missing values with placeholder
paste -d',' short.txt medium.txt long.txt | \
sed 's/^,/MISSING,/; s/,,/,MISSING,/g; s/,$/,MISSING/'
# Count lines per file
echo "short.txt: $(wc -l < short.txt) lines"
echo "medium.txt: $(wc -l < medium.txt) lines"
echo "long.txt: $(wc -l < long.txt) lines"
echo "paste output: $(paste short.txt medium.txt long.txt | wc -l) lines"
# Use awk to handle missing data
paste -d',' short.txt medium.txt long.txt | \
awk -F',' '{
if ($1 == "") $1 = "N/A"
if ($2 == "") $2 = "N/A"
if ($3 == "") $3 = "N/A"
print $1 "," $2 "," $3
}'
# Tab-delimited:
A 1 X
B 2 Y
C 3 Z
4 W
5 Q
R
S
# Comma-delimited (empty fields visible):
A,1,X
B,2,Y
C,3,Z
,4,W
,5,Q
,,R
,,S
# With placeholders:
A,1,X
B,2,Y
C,3,Z
MISSING,4,W
MISSING,5,Q
MISSING,MISSING,R
MISSING,MISSING,S
# Output line count:
short.txt: 3 lines
medium.txt: 5 lines
long.txt: 7 lines
paste output: 7 lines (longest file determines output length)
When merging files of different lengths, paste continues until all files are exhausted. Shorter files contribute empty fields. Always verify your data integrity when files might have different lengths.
# Create sample data
cat > col1.txt << 'EOF'
Name
Alice
Bob
Charlie
EOF
cat > col2.txt << 'EOF'
Age
25
30
35
EOF
cat > col3.txt << 'EOF'
City
NYC
LA
Chicago
EOF
# Cycle through delimiters: | then ,
paste -d'|,' col1.txt col2.txt col3.txt
# Create a table with | and spaces
paste -d'| ' col1.txt col2.txt col3.txt
# Complex delimiter pattern
paste -d':;,' col1.txt col2.txt col3.txt col1.txt
# Create markdown-style table
echo "| Column1 | Column2 | Column3 |"
echo "|---------|---------|---------|"
paste col1.txt col2.txt col3.txt | \
awk -F'\t' '{printf "| %-8s| %-8s| %-8s|\n", $1, $2, $3}'
# Pattern for key-value pairs
paste -d'=' col1.txt col2.txt | sed 's/^/export /'
# Create INI-style config
echo "[Settings]"
paste -d'=' col1.txt col2.txt
# Cycling | and , :
Name|Age,City
Alice|25,NYC
Bob|30,LA
Charlie|35,Chicago
# Delimiter pattern cycles through characters:
Name:Age;City,Name
Alice:25;NYC,Alice
Bob:30;LA,Bob
Charlie:35;Chicago,Charlie
# Markdown table:
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| Name | Age | City |
| Alice | 25 | NYC |
| Bob | 30 | LA |
| Charlie | 35 | Chicago |
# Key-value exports:
export Name=Age
export Alice=25
export Bob=30
export Charlie=35
# INI format:
[Settings]
Name=Age
Alice=25
Bob=30
Charlie=35
Delimiter cycling allows creative formatting. Each separator position uses the next character in the delimiter string, then wraps back to the beginning. This is powerful for creating structured formats like tables and config files.
# Convert single column to multiple columns (4 columns)
seq 1 20 | paste - - - -
# Convert to 3 columns with serial mode
seq 1 12 | paste - - -
# Create key-value pairs from two lists
cat > keys.txt << 'EOF'
user
pass
host
port
EOF
cat > values.txt << 'EOF'
admin
secret123
localhost
5432
EOF
paste -d'=' keys.txt values.txt
# Transpose a matrix (swap rows and columns)
cat > matrix.txt << 'EOF'
1 2 3
4 5 6
7 8 9
EOF
# Simple transpose for small data
paste <(awk '{print $1}' matrix.txt) \
<(awk '{print $2}' matrix.txt) \
<(awk '{print $3}' matrix.txt)
# Create pairs from a single list
cat > items.txt << 'EOF'
A
B
C
D
E
F
EOF
# Pair consecutive items
paste - - < items.txt
# Create overlapping pairs (sliding window)
paste items.txt <(tail -n +2 items.txt)
# Interleave two files
cat > odd.txt << 'EOF'
1
3
5
EOF
cat > even.txt << 'EOF'
2
4
6
EOF
paste odd.txt even.txt | tr '\t' '\n'
# Convert space-separated to newline-separated
echo "one two three four five" | tr ' ' '\n' | paste -s -d' '
# Reverse operation: split line to multiple lines
echo "a,b,c,d,e" | tr ',' '\n'
# 4 columns from sequence:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20
# Key-value pairs:
user=admin
pass=secret123
host=localhost
port=5432
# Transposed matrix:
1 4 7
2 5 8
3 6 9
# Consecutive pairs:
A B
C D
E F
# Sliding window pairs:
A B
B C
C D
D E
E F
# Interleaved:
1
2
3
4
5
6
These transformations are essential for data wrangling. The pattern paste - - - creates 3 columns by reading stdin three times. This technique is widely used for reformatting data into different layouts.
# Add line numbers to existing data
paste <(seq 1 4) names.txt ages.txt
# Create a columnar report with headers
{
echo -e "ID\tName\tAge"
paste <(seq 1 4) names.txt ages.txt
} | column -t
# Merge sorted files with indicators
paste <(sort file1.txt) <(sort file2.txt) | \
awk -F'\t' '{
if ($1 == $2) print $1 " [BOTH]"
else if ($1 != "") print $1 " [FILE1]"
else print $2 " [FILE2]"
}'
# Calculate differences between columns
cat > jan.txt << 'EOF'
100
150
200
250
EOF
cat > feb.txt << 'EOF'
110
145
210
260
EOF
paste jan.txt feb.txt | \
awk '{diff=$2-$1; pct=($2-$1)/$1*100;
printf "%d\t%d\t%+d\t%+.1f%%\n", $1, $2, diff, pct}'
# Create a lookup table from two files
paste -d':' \
<(cut -d',' -f1 users.csv) \
<(cut -d',' -f3 users.csv)
# Merge multiple log files with timestamps
paste \
<(grep "ERROR" app1.log | awk '{print $1, $2}') \
<(grep "ERROR" app2.log | awk '{print $3}') \
| sort
# Generate SQL INSERT statements
paste names.txt ages.txt cities.txt | \
awk -F'\t' '{
printf "INSERT INTO users (name, age, city) VALUES ('\''%s'\'', %s, '\''%s'\'');\n",
$1, $2, $3
}'
# Create a comparison table
paste -d'|' \
<(ls -1 dir1/) \
<(ls -1 dir2/) | \
column -t -s'|'
# Numbered report with headers:
ID Name Age
1 Alice 25
2 Bob 30
3 Charlie 35
4 David 40
# Difference calculation:
100 110 +10 +10.0%
150 145 -5 -3.3%
200 210 +10 +5.0%
250 260 +10 +4.0%
# SQL INSERT statements:
INSERT INTO users (name, age, city) VALUES ('Alice', 25, 'NYC');
INSERT INTO users (name, age, city) VALUES ('Bob', 30, 'LA');
INSERT INTO users (name, age, city) VALUES ('Charlie', 35, 'Chicago');
INSERT INTO users (name, age, city) VALUES ('David', 40, 'Houston');
# Directory comparison:
file1.txt file1.txt
file2.txt
file3.txt file3.txt
file4.txt
Combining paste with awk is especially powerful for calculations and formatting. The ability to process multiple columns simultaneously enables complex data transformations in compact pipelines.
# Combine access and error logs by timestamp
cat > access.log << 'EOF'
2025-12-14 10:00 GET /api/users 200
2025-12-14 10:01 POST /api/login 200
2025-12-14 10:02 GET /api/data 500
2025-12-14 10:03 GET /api/status 200
EOF
cat > error.log << 'EOF'
2025-12-14 10:00 -
2025-12-14 10:01 -
2025-12-14 10:02 Database connection failed
2025-12-14 10:03 -
EOF
# Merge logs side by side
paste -d'|' access.log error.log | \
grep -v '|-$' | \
awk -F'|' '{print $1 " [ERROR] " $2}'
# Extract and compare metrics from two servers
cat > server1_metrics.txt << 'EOF'
CPU: 45%
Memory: 2.3GB
Disk: 67%
EOF
cat > server2_metrics.txt << 'EOF'
CPU: 52%
Memory: 3.1GB
Disk: 71%
EOF
echo "Metric Server1 Server2"
echo "--------------------------------"
paste server1_metrics.txt server2_metrics.txt | \
awk -F'\t' '{
split($1, a, ": ")
split($2, b, ": ")
printf "%-10s %-10s %-10s\n", a[1], a[2], b[2]
}'
# Create hourly report from logs
cat > hourly_requests.log << 'EOF'
00:00 234
01:00 189
02:00 156
03:00 142
04:00 167
EOF
cat > hourly_errors.log << 'EOF'
00:00 3
01:00 2
02:00 1
03:00 0
04:00 2
EOF
echo "Hour Requests Errors Error%"
echo "================================"
paste hourly_requests.log hourly_errors.log | \
awk '{
hour=$1
requests=$2
errors=$4
if (requests > 0) {
pct = (errors/requests)*100
} else {
pct = 0
}
printf "%s %-9d %-7d %.2f%%\n", hour, requests, errors, pct
}'
# Merge user activity from multiple sources
paste \
<(cut -d',' -f1,2 web_activity.csv) \
<(cut -d',' -f2 mobile_activity.csv) \
<(cut -d',' -f2 api_activity.csv) | \
awk -F'\t' '{
total = $2 + $3 + $4
printf "%s: Web=%d Mobile=%d API=%d Total=%d\n",
$1, $2, $3, $4, total
}'
# Merged error log:
2025-12-14 10:00 GET /api/users 200 [ERROR] 2025-12-14 10:02 Database connection failed
# Server comparison:
Metric Server1 Server2
--------------------------------
CPU 45% 52%
Memory 2.3GB 3.1GB
Disk 67% 71%
# Hourly report:
Hour Requests Errors Error%
================================
00:00 234 3 1.28%
01:00 189 2 1.06%
02:00 156 1 0.64%
03:00 142 0 0.00%
04:00 167 2 1.20%
# User activity:
user1: Web=145 Mobile=67 API=23 Total=235
user2: Web=89 Mobile=102 API=45 Total=236
user3: Web=201 Mobile=34 API=12 Total=247
These patterns are production-ready for log analysis. Paste excels at correlating data from multiple log sources, creating unified reports, and calculating metrics across disparate data files.
#!/bin/bash
# File: data_correlator.sh
# Correlate and validate data from multiple sources
set -euo pipefail
# ============================================
# Configuration
# ============================================
readonly DATA_DIR="${1:-.}"
readonly OUTPUT_DIR="${2:-./output}"
readonly LOG_FILE="$OUTPUT_DIR/correlation.log"
mkdir -p "$OUTPUT_DIR"
# ============================================
# Logging
# ============================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
# ============================================
# Data Validation
# ============================================
validate_files() {
local -a files=("$@")
log "Validating input files..."
for file in "${files[@]}"; do
if [ ! -f "$file" ]; then
log "ERROR: File not found: $file"
exit 1
fi
local lines=$(wc -l < "$file")
log " $file: $lines lines"
done
# Check if all files have same length
local first_len=$(wc -l < "${files[0]}")
for file in "${files[@]:1}"; do
local file_len=$(wc -l < "$file")
if [ "$file_len" != "$first_len" ]; then
log "WARNING: File length mismatch: ${files[0]}($first_len) vs $file($file_len)"
fi
done
}
# ============================================
# Correlation Functions
# ============================================
correlate_data() {
local id_file="$1"
local data1_file="$2"
local data2_file="$3"
local output_file="$4"
log "Correlating data..."
log " IDs: $id_file"
log " Data1: $data1_file"
log " Data2: $data2_file"
log " Output: $output_file"
# Create header
echo -e "ID\tData1\tData2\tDifference\tPercent_Change" > "$output_file"
# Correlate and calculate
paste "$id_file" "$data1_file" "$data2_file" | \
awk -F'\t' '
NR > 1 {
id = $1
val1 = $2
val2 = $3
diff = val2 - val1
if (val1 != 0) {
pct = (diff / val1) * 100
} else {
pct = 0
}
printf "%s\t%.2f\t%.2f\t%+.2f\t%+.1f%%\n",
id, val1, val2, diff, pct
}' >> "$output_file"
local rows=$(($(wc -l < "$output_file") - 1))
log "Processed $rows data rows"
}
# ============================================
# Anomaly Detection
# ============================================
detect_anomalies() {
local data_file="$1"
local threshold="$2"
local output_file="$3"
log "Detecting anomalies (threshold: ${threshold}%)..."
echo -e "ID\tData1\tData2\tChange%" > "$output_file"
awk -F'\t' -v thresh="$threshold" '
NR > 1 {
# Extract percent change (remove % sign)
gsub(/%/, "", $5)
pct = $5
# Remove + sign for comparison
gsub(/\+/, "", pct)
if (pct > thresh || pct < -thresh) {
print $0
}
}' "$data_file" >> "$output_file"
local anomalies=$(($(wc -l < "$output_file") - 1))
log "Found $anomalies anomalies"
}
# ============================================
# Report Generation
# ============================================
generate_summary() {
local data_file="$1"
local output_file="$2"
log "Generating summary report..."
{
echo "======================================="
echo "Data Correlation Summary Report"
echo "Generated: $(date)"
echo "======================================="
echo ""
# Statistics
awk -F'\t' '
NR > 1 {
sum_d1 += $2
sum_d2 += $3
sum_diff += $4
count++
if ($2 > max_d1 || NR == 2) max_d1 = $2
if ($2 < min_d1 || NR == 2) min_d1 = $2
if ($3 > max_d2 || NR == 2) max_d2 = $3
if ($3 < min_d2 || NR == 2) min_d2 = $3
}
END {
printf "Total Records: %d\n\n", count
printf "Data1 Statistics:\n"
printf " Average: %.2f\n", sum_d1/count
printf " Min: %.2f\n", min_d1
printf " Max: %.2f\n\n", max_d1
printf "Data2 Statistics:\n"
printf " Average: %.2f\n", sum_d2/count
printf " Min: %.2f\n", min_d2
printf " Max: %.2f\n\n", max_d2
printf "Change Statistics:\n"
printf " Average Difference: %+.2f\n", sum_diff/count
printf " Total Change: %+.2f\n", sum_diff
}' "$data_file"
echo ""
echo "======================================="
} > "$output_file"
log "Summary saved to: $output_file"
}
# ============================================
# Main Processing
# ============================================
main() {
log "========================================="
log "Data Correlation Tool"
log "========================================="
# Sample data creation (in real use, these would exist)
cat > "$DATA_DIR/ids.txt" << 'EOF'
ID
USER001
USER002
USER003
USER004
USER005
EOF
cat > "$DATA_DIR/baseline.txt" << 'EOF'
Baseline
100.50
150.25
200.00
175.75
225.50
EOF
cat > "$DATA_DIR/current.txt" << 'EOF'
Current
105.25
148.00
210.50
175.80
250.00
EOF
# Validate inputs
validate_files \
"$DATA_DIR/ids.txt" \
"$DATA_DIR/baseline.txt" \
"$DATA_DIR/current.txt"
# Correlate data
correlate_data \
"$DATA_DIR/ids.txt" \
"$DATA_DIR/baseline.txt" \
"$DATA_DIR/current.txt" \
"$OUTPUT_DIR/correlation.tsv"
# Detect anomalies (>10% change)
detect_anomalies \
"$OUTPUT_DIR/correlation.tsv" \
10 \
"$OUTPUT_DIR/anomalies.tsv"
# Generate summary
generate_summary \
"$OUTPUT_DIR/correlation.tsv" \
"$OUTPUT_DIR/summary.txt"
# Display results
log ""
log "Results:"
log " Correlation: $OUTPUT_DIR/correlation.tsv"
log " Anomalies: $OUTPUT_DIR/anomalies.tsv"
log " Summary: $OUTPUT_DIR/summary.txt"
log ""
cat "$OUTPUT_DIR/summary.txt"
log "========================================="
log "Processing complete"
}
main "$@"
[2025-12-14 16:45:00] =========================================
[2025-12-14 16:45:00] Data Correlation Tool
[2025-12-14 16:45:00] =========================================
[2025-12-14 16:45:00] Validating input files...
[2025-12-14 16:45:00] ./ids.txt: 6 lines
[2025-12-14 16:45:00] ./baseline.txt: 6 lines
[2025-12-14 16:45:00] ./current.txt: 6 lines
[2025-12-14 16:45:00] Correlating data...
[2025-12-14 16:45:00] Processed 5 data rows
[2025-12-14 16:45:00] Detecting anomalies (threshold: 10%)...
[2025-12-14 16:45:00] Found 2 anomalies
[2025-12-14 16:45:00] Generating summary report...
=======================================
Data Correlation Summary Report
Generated: Sun Dec 14 16:45:00 EST 2025
=======================================
Total Records: 5
Data1 Statistics:
Average: 170.40
Min: 100.50
Max: 225.50
Data2 Statistics:
Average: 177.91
Min: 105.25
Max: 250.00
Change Statistics:
Average Difference: +7.51
Total Change: +37.55
=======================================
# correlation.tsv:
ID Data1 Data2 Difference Percent_Change
USER001 100.50 105.25 +4.75 +4.7%
USER002 150.25 148.00 -2.25 -1.5%
USER003 200.00 210.50 +10.50 +5.3%
USER004 175.75 175.80 +0.05 +0.0%
USER005 225.50 250.00 +24.50 +10.9%
# anomalies.tsv shows USER005 (10.9% change)
This production script demonstrates best practices: input validation, logging, error handling, modular functions, and comprehensive reporting. It uses paste as the foundation for correlating multiple data sources and performing analysis.
-d','
for CSV output or cat -A to see tabs as ^I in output for verification.
paste -s to convert multiple lines into a single line. Perfect for creating
comma-separated lists from vertical data: paste -s -d','
wc -l file1 file2
paste -d':;,' uses : for
first separator, ; for second, , for third, then wraps back to :
paste file1 file2 | awk '{print $1, $2, $1+$2}'
cat file | paste - - - creates
3 columns from sequential lines. Great for reformatting data.
cat -A to verify actual delimiters used.
column -t for human-readable aligned columns. Perfect
for reports: paste file1 file2 | column -t