Display two files side by side
Solution 1
You can use pr
to do this, using the -m
flag to merge the files, one per column, and -t
to omit headers, eg.
pr -m -t one.txt two.txt
outputs:
apple The quick brown fox..
pear foo
longer line than the last two bar
last line linux
skipped a line
See Also:
Solution 2
To expand a bit on @Hasturkun's answer: by default pr
uses only 72 columns for its output, but it's relatively easy to make it use all available columns of your terminal window:
pr -w $COLUMNS -m -t one.txt two.txt
Most shells will store (and update) your terminal's screenwidth in the $COLUMNS
shell variable, so we're just passing that value on to pr
to use for its output's width setting.
This also answers @Matt's question:
Is there a way for pr to auto-detect screen width?
So, no: pr
itself can't detect the screenwidth, but we're helping it out a bit by passing in the terminal's width via its -w
option.
Note that $COLUMNS
is a shell variable, not an environment variable, so it isn't exported to child processes, and hence the above approach will likely not work in scripts, only in interactive TTYs... see LINES and COLUMNS environmental variables lost in a script for alternative approaches.
Solution 3
If you know the input files have no tabs, then using expand
simplifies @oyss's answer:
paste one.txt two.txt | expand --tabs=50
If there could be tabs in the input files, you can always expand first:
paste <(expand one.txt) <(expand two.txt) | expand --tabs=50
Solution 4
paste one.txt two.txt | awk -F'\t' '{
if (length($1)>max1) {max1=length($1)};
col1[NR] = $1; col2[NR] = $2 }
END {for (i = 1; i<=NR; i++) {printf ("%-*s %s\n", max1, col1[i], col2[i])}
}'
Using *
in a format specification allows you to supply the field length dynamically.
Solution 5
There is a sed
way:
f1width=$(wc -L <one.txt)
f1blank="$(printf "%${f1width}s" "")"
paste one.txt two.txt |
sed "
s/^\(.*\)\t/\1$f1blank\t/;
s/^\(.\{$f1width\}\) *\t/\1 /;
"
Under bash, you could use printf -v
:
f1width=$(wc -L <one.txt)
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
sed "s/^\(.*\)\t/\1$f1blank\t/;
s/^\(.\{$f1width\}\) *\t/\1 /;"
(Of course @Hasturkun 's solution pr
is the most accurate!):
Advantage of sed
over pr
You can finely choose separation width and or separators:
f1width=$(wc -L <one.txt)
(( f1width += 4 )) # Adding 4 spaces
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
sed "s/^\(.*\)\t/\1$f1blank\t/;
s/^\(.\{$f1width\}\) *\t/\1 /;"
Or, for sample, to mark lines containing line
:
f1width=$(wc -L <one.txt)
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
sed "s/^\(.*\)\t/\1$f1blank\t/;
/line/{s/^\(.\{$f1width\}\) *\t/\1 |ln| /;ba};
s/^\(.\{$f1width\}\) *\t/\1 | | /;:a"
will render:
apple | | The quick brown fox..
pear | | foo
longer line than the last two |ln| bar
last line |ln| linux
| |
|ln| skipped a line
Related videos on Youtube
Chris Seymour
Updated on July 08, 2022Comments
-
Chris Seymour almost 2 years
How can 2 unsorted text files of different lengths be display side by side (in columns) in a
shell
Given
one.txt
andtwo.txt
:$ cat one.txt apple pear longer line than the last two last line $ cat two.txt The quick brown fox.. foo bar linux skipped a line
Display:
apple The quick brown fox.. pear foo longer line than the last two bar last line linux skipped a line
paste one.txt two.txt
almost does the trick but doesn't align the columns nicely as it just prints one tab between column 1 and 2. I know how to this with emacs and vim but want the output displayed to stdout for piping ect.The solution I came up with uses
sdiff
and then pipes to sed to remove the outputsdiff
adds.sdiff one.txt two.txt | sed -r 's/[<>|]//;s/(\t){3}//'
I could create a function and stick it in my
.bashrc
but surely a command for this exists already (or a cleaner solution potentially)?-
fedorqui over 7 yearsNot in a shell, but worth mentioning: use meld!
-
-
Chris Seymour over 11 yearsPerfect! Knew something would exist, never heard of
pr
before. I tried with 3 files and the output was truncated but the-w
option solved that. Nice answer. -
Hasturkun over 11 years@sudo_o: Happy to help, coreutils is full of gems
-
Chris Seymour over 10 years
sdiff
isdiff -y
which I discuss in the question. -
Vikas Jain over 10 yearsYes right... it was mentioned to show another command/flag setting of doing it.
-
Chris Seymour over 10 yearsBut it doesn't answer the questions
diff
adds characters between the two files. -
Matt about 10 yearsIs there a way for pr to auto-detect screen width?
-
Hasturkun almost 10 years@Matt: You could use
$COLUMNS
, which should be provided by the shell. -
molnarg about 9 yearsWhen used to print two files side by side,
pr
cuts the end of long lines. Is there a way to make it wrap the lines? -
crw almost 7 years@molnarg: One method is to first fold each input file to half the page width, less any column-separator width. EG, in
bash
:pr -t -m -w $PAGE_WIDTH <(fold -w $HALF_PAGE_WIDTH one.txt) <(fold -w $HALF_PAGE_WIDTH two.txt)
. This could be solved elegantly in user-created script. -
Ashutosh Baheti over 6 yearsIs there a way to show 1 line from first file and 10 lines from the second file? Its machine translation outputs that I want to view side by side.
-
Lichtgestalt almost 4 years
pr -mtJ ...
to use all available width. -
alper over 3 yearscan I apply this for output of two processes instead of a file?
-
Jishnu P Das about 3 years
bash f1width=$(wc -L <one.txt) printf -v f1blank "%${f1width}s" paste one.txt two.txt | sed "s/^\(.*\)\t/\1$f1blank\t/; /line/{s/^\(.\{$f1width\}\) *\t/\1 |ln| /;ba}; s/^\(.\{$f1width\}\) *\t/\1 | | /;:a"
Nice solution!! really helpful in other contexts -
Graham Toal about 2 yearsThanks for the hints here. I've used it in a bash script: pr -m -t -w$((2 * $(cat $1 $2|wc -L))) $1 $2