7

I want to output two text files in two columns — one on the left side and other one on the right.

paste doesn't solve the problem, because it only insert a character as delimiter, so if the first file has lines of different lengths output will be twisted:

$ cat file1
looooooooong line
line
$ cat file2
hello
world
$ paste file1 file2
looooooooong line   hello
line    world

If there was a command to add trailing spaces like fmt --add-spaces --width 50 the problem would be solved(1):

$ paste <(fmt --add-spaces --width 50 file1) file2
looooooooong line                                 hello
line                                              world

But I don't know a simple way to do this.

So how to merge files horizontally and print them to standard output without twisting?

In fact I just want to read them side-by-side.


(1) UPD: command to add trailing spaces does exist, e. g. xargs -d '\n' printf '%-50s\n'. But running
$ paste <(add-trailing-spaces file1) file2 won't produce expected visual output when file1 has fewer lines than file2.

1

4 Answers 4

12

With single pr command:

pr -Tm file[12]
  • -T (--omit-pagination) - omit page headers and trailers, eliminate any pagination by form feeds set in input files

  • -m (--merge) - print all files in parallel, one in each column

3
  • What does the -T do?
    – Kusalananda
    Sep 16, 2017 at 18:37
  • This can truncate long lines without any warning, but I like it.
    – belkka
    Sep 16, 2017 at 19:54
  • On my mac I had to use pr -tm file[12]. (minus -t)
    – Ulysse BN
    Oct 15, 2019 at 9:37
9

What about paste file{1,2}| column -s $'\t' -tn?

looooooooong line line  hello
line                    world
  • This is telling column to use Tab as columns' separator where we takes it from the paste command which is the default seperator there if not specified; generally:

    paste -d'X' file{1,2}| column -s $'X' -tn

    where X means any single character. You need to choose the one which granted that won't be occur in your files.

  • The -t option is used to determine the number of columns the input contains.

  • This will not add long tab between two files while other answers does.
  • this will work even if there was empty line(s) in file1 and it will not print second file in print area of file1, see below input/ouput

    Input file1:

    looooooooong line
    
    line
    

    Input file2:

    hello
    world
    

    Output:

    looooooooong line  hello
                       world
    line
    
7
  • 1
    Generally paste -d @ file1 file2 | column -t -n -s @ where @ is any delimiter that is not contained in files.
    – belkka
    Sep 16, 2017 at 18:46
  • @belkka exactly Jul 28, 2018 at 18:02
  • I had been trying this but without the $. This is the answer for me, but could you explain what the $ is doing here?
    – paradroid
    Sep 27, 2019 at 16:55
  • 1
    @paradroid please see gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html Sep 27, 2019 at 17:11
  • I get -n requires an argument. Isn't that used for naming the table?
    – einpoklum
    Nov 29, 2022 at 10:22
1

A portable solution:

$ paste file1 file2 | awk -F'\t' '{ printf("%-30s %s\n", $1, $2) }'
looooooooong line              hello
line                           world

This uses paste to produce a tab-delimited input for awk.

The awk script simply takes the two tab-delimited fields and outputs them using printf(). A column of 30 characters is reserved for the first file. The %-30s means "30 positions of string data with left alignment". Removing the - would produce a column aligned to the right, and changing 30 would change the column width.

It also deals with uneven length files. Here I've added lines to the second file:

looooooooong line              hello
line                           world
                               hello
                               world
                               hello
                               world

And, when reversing the order of the files on the command line:

hello                          looooooooong line
world                          line
hello
world
hello
world
1

Try:

paste -d '\n' file1 file2 | xargs -d '\n' printf '%-30s  %-30s\n'

Inspired by @Kusalananda's solution.

Note: The -d parameter of xargs is only available on GNU version, but not on BSD.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .