Hacker Public Radio
Hacker Public Radio
Hacker Public Radio
HPR4687: UNIX Curio #11 - Merging Files
1 seconds Posted Jul 21, 2026 at 12:00 am.
0:00
0:01
Download MP3
Show notes
ether
This series is dedicated to exploring little-known—and occasionally useful—trinkets lurking in the dusty corners of UNIX-like operating systems.
I frequently find myself reaching for the
cut
utility when writing scripts to extract one piece of data from a line, or to select specific fields from a log file. While I am familiar with its counterpart,
paste
, I don't employ it very often because I don't typically need its functionality.
This perhaps has to do with the fact that I rarely work with text files containing lists. For shorter lists, I usually end up using a spreadsheet and for larger ones, a relational database. Both are valuable tools with their own strengths and weaknesses, but it is good to also know about standard utilities for working with lists. After uploading UNIX Curio #8 (
HPR episode 4657
), I felt like maybe I had been too dismissive of the
comm
utility in that episode and should talk more about tools that are useful when managing lists.
I don't frequently find myself using
paste
1
, but can explain how it works. Briefly, it is a rough opposite of
cut
—when given multiple files as arguments, it assembles the first line from each one separated by tabs, then the second line, and so on. Instead of tabs, a different delimiter can be chosen with the
-d
option. Another option is
-s
, which swaps rows and columns so that the contents of each named file would appear on one line. While
paste
itself doesn't qualify as a UNIX Curio in my opinion, there is one feature that does: a hyphen can be given as an argument multiple times. In this special case, the output is taken line by line from standard input, but is spread across as many columns as there are hyphens.
Example of using
paste
to turn the output of
ls
into columns. Because these columns are separated by tabs, they don't necessarily line up when a filename is eight or more characters long. The
-1
is not required for the second
ls
command since that behavior is implied when output isn't going to a terminal. The
-C
option to
ls
usually gives nicer-looking output on a terminal—also, it lists in ascending order down by column. (Most implementations default to
-C
when output goes to a terminal.) If you want items ascending along rows like the
paste
example does, try
ls -x
instead.
$ ls -1 /proc/net
anycast6
arp
bnep
connector
dev
dev_mcast
dev_snmp6
fib_trie
fib_triestat
hci
icmp
icmp6
if_inet6
igmp
igmp6
ip6_flowlabel
ip6_mr_cache
ip6_mr_vif
ip_mr_cache
ip_mr_vif
ip_tables_matches
ip_tables_names
[...35 more entries not shown...]
$ ls /proc/net | paste - - - -
anycast6 arp bnep connector
dev dev_mcast dev_snmp6 fib_trie
fib_triestat hci icmp icmp6
if_inet6 igmp igmp6 ip6_flowlabel
ip6_mr_cache ip6_mr_vif ip_mr_cache ip_mr_vif
ip_tables_matches ip_tables_names ip_tables_targets ipv6_route
l2cap mcfilter mcfilter6 netfilter
netlink netstat packet protocols
psched ptype raw raw6
rfcomm route rt6_stats rt_acct
rt_cache sco snmp snmp6
sockstat sockstat6