3

I am looking from something which gives me an output of comm -3 on two sorted outputs (line-by-line comparison, only additional/missing lines from either side) but which looks more like the output from diff -y, e.g. in that it uses the whole width.

file1:

bar/a
bar/feugiat
bar/libero
bar/mauris
bar/scelerisque
bar/urna
foo/blandit
foo/elementum
foo/feugiat
foo/laoreet
foo/luctus
foo/non
foo/pellentesque
foo/pulvinar
foo/rutrum
foo/sed
foo/ut
foo/vivamus

file2:

bar/a
bar/molestie
bar/quam
bar/risus
bar/tristique
foo/blandit
foo/elementum
foo/feugiat
foo/ligula
foo/massa
foo/mauris
foo/metus
foo/pellentesque
foo/pulvinar
foo/ut

Output from comm -3 file1 file2:

bar/feugiat
bar/libero
bar/mauris
        bar/molestie
        bar/quam
        bar/risus
bar/scelerisque
        bar/tristique
bar/urna
foo/laoreet
        foo/ligula
foo/luctus
        foo/massa
        foo/mauris
        foo/metus
foo/non
foo/rutrum
foo/sed
foo/vivamus

Output from diff -y --suppress-common-lines file1 file2 (GNU), it depends on the screen width:

bar/feugiat                                                   | bar/molestie
bar/libero                                                    | bar/quam
bar/mauris                                                    | bar/risus
bar/scelerisque                                               | bar/tristique
bar/urna                                                      <
foo/laoreet                                                   | foo/ligula
foo/luctus                                                    | foo/massa
foo/non                                                       | foo/mauris
                                                              > foo/metus
foo/rutrum                                                    / foo/ut
foo/sed                                                       <
foo/ut                                                        <
foo/vivamus                                                   <

Possible output I would wish for:

bar/feugiat                                                   <
bar/libero                                                    <
bar/mauris                                                    <
                                                              > bar/molestie
                                                              > bar/quam
                                                              > bar/risus
bar/scelerisque                                               <
                                                              > bar/tristique
bar/urna                                                      <
foo/laoreet                                                   <
                                                              > foo/ligula
foo/luctus                                                    <
                                                              > foo/massa
                                                              > foo/mauris
                                                              > foo/metus
foo/non                                                       <
foo/rutrum                                                    <
foo/sed                                                       <
foo/vivamus                                                   <

Without the arrows would be OK as well, just the screen width should be used better:

bar/feugiat
bar/libero
bar/mauris
                                                                bar/molestie
                                                                bar/quam
                                                                bar/risus
bar/scelerisque
                                                                bar/tristique
bar/urna
foo/laoreet
                                                                foo/ligula
foo/luctus
                                                                foo/massa
                                                                foo/mauris
                                                                foo/metus
foo/non
foo/rutrum
foo/sed
foo/vivamus
phk
  • 5,953
  • 7
  • 42
  • 71

1 Answers1

6

You could pipe to:

expand -t "$((${COLUMNS:-$(tput cols)} / 2))"

Or for the angle brackets:

awk -v cols="${COLUMNS:-$(tput cols)}" '
  BEGIN {width = cols/2-1; space = sprintf("%*s", width, "")}
  /^\t/ {print space ">", substr($0, 2); next}
  {printf "%-*s<\n", width, $0}'

If your tput doesn't output the number of columns, you could try parsing the output of stty size or stty -a. Or use zsh -c 'echo $COLUMNS' (also works with mksh). There's no standard/portable way to get that information.

If the input files contain multi-byte or double-width characters, YMMV. Depending on the expand/awk implementation alignment may be off.

That also assumes that the input files have no line that start with a Tab character. If that can't be guaranteed, the GNU implementation of comm has a --output-delimiter which you could use to specify a unique string. Or you could implement the comm functionality in awk which shouldn't be too complicated.

  • Or ttysize w on some busyboxes, or my script from http://unix.stackexchange.com/a/283206/117599.Great answer, pretty much what I wanted! – phk Feb 24 '17 at 13:48