22

cat file1

foo
ice
two

cat file2

bar
cream
hundred

Desired output:

foobar
icecream
twohundred

file1 and file2 will always have the same amount of lines in my scenario, in case that makes things easier.

5 Answers 5

36

The right tool for this job is probably paste

paste -d '' file1 file2

See man paste for details.


You could also use the pr command:

pr -TmJS"" file1 file2

where

  • -T turns off pagination
  • -mJ merge files, Joining full lines
  • -S"" separate the columns with an empty string

If you really wanted to do it using pure bash shell (not recommended), then this is what I'd suggest:

while IFS= read -u3 -r a && IFS= read -u4 -r b; do 
  printf '%s%s\n' "$a" "$b"
done 3<file1 4<file2

(Only including this because the subject came up in comments to another proposed pure-bash solution.)

2
  • 1
    Awesome, thank you for the very simple solution. Should I ever worry about portability when it comes to using paste?
    – TuxForLife
    Apr 30, 2015 at 2:46
  • 1
    @user264974 paste is in GNU Coreutils so you're probably fairly safe.
    – nettux
    Apr 30, 2015 at 9:00
9

Through way:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2" reads the entire line from file2 and holds into x variable.
  • print $0x prints the whole line from file1 by using $0 then x which is the saved line of file2.
1
  • Very good to have an awk alternative, I may use this instead!
    – TuxForLife
    May 6, 2015 at 18:21
4

paste is the way to go. If you want to check some other methods, here is a python solution:

#!/usr/bin/env python2
import itertools
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    lines = itertools.izip_longest(f1, f2)
    for a, b in lines:
        if a and b:
            print a.rstrip() + b.rstrip()
        else:
            if a:
                print a.rstrip()
            else:
                print b.rstrip()

If you have few number of lines:

#!/usr/bin/env python2
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    print '\n'.join((a.rstrip() + b.rstrip() for a, b in zip(f1, f2)))

Note that for unequal number of lines, this one will end at the last line of the file that ends first.

3

Also, with pure bash (notice that this will totally ignore empty lines):

#!/bin/bash

IFS=$'\n' GLOBIGNORE='*'
f1=($(< file1))
f2=($(< file2))
i=0
while [ "${f1[${i}]}" ] && [ "${f2[${i}]}" ]
do
    echo "${f1[${i}]}${f2[${i}]}" >> out
    ((i++))
done
while [ "${f1[${i}]}" ]
do
    echo "${f1[${i}]}" >> out
    ((i++))
done
while [ "${f2[${i}]}" ]
do
    echo "${f2[${i}]}" >> out
    ((i++))
done
4
  • This is just plain wrong. It doesn't work at all. Either use mapfile to read the files into arrays, or use a while loop with two read commands, reading from each their fd.
    – geirha
    Apr 30, 2015 at 11:07
  • @geirha You're right, I messed up with the syntax, it's ok now.
    – kos
    Apr 30, 2015 at 11:17
  • not quite. With the updated code, empty lines will be ignored, and if any line contains glob characters, the line might be replaced with matching filenames. So never use array=( $(cmd) ) or array=( $var ). Use mapfile instead.
    – geirha
    Apr 30, 2015 at 12:29
  • @geirha You're right of course, I took care of the glob characters but I left the newline ignored, because in order to do that and in order to make a decent solution out of it it needs to be rewritten. I specified this and 'll leave this version in case it's going to be useful to somebody in the meantime. Thanks for your points so far.
    – kos
    Apr 30, 2015 at 14:51
2

The perl way, easy to understand:

#!/usr/bin/perl
$filename1=$ARGV[0];
$filename2=$ARGV[1];

open(my $fh1, "<", $filename1) or die "cannot open < $filename1: $!";
open(my $fh2, "<", $filename2) or die "cannot open < $filename2: $!";

my @array1;
my @array2;

while (my $line = <$fh1>) {
  chomp $line;
  push @array1, $line;
}
while (my $line = <$fh2>) {
  chomp $line;
  push @array2, $line;
}

for my $i (0 .. $#array1) {
  print @array1[$i].@array2[$i]."\n";
}

Start with:

./merge file1 file2

Output:

foobar
icecream
twohundred

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.