jO.
jO.

Reputation: 3512

concatenate files in a pairwise manner

I would like to concatenate existing .txt files within a directory in a pairwise manner -creating all possible combinations of the original files. Im not sure how to go about using bash or zsh shell scripting, not really my strong suit. I guess one would need to output new files to another directory, preventing an exponential increase of combinations.

Below is a dummy example. In reality I have more files.

echo 'A' > A.txt
echo 'B' > B.txt
echo 'C' > C.txt

where A + B is the same as B + A and the order has no importance.

Desired output:

>ls
AB.txt AC.txt BC.txt

>head AB.txt
# A
# B
>head AC.txt
# A
# C
>head BC.txt
# B
# C

The below is an attempt (at something...)

#!/bin/zsh

counter = 1
for i in *.txt; do
    cat $i $counter $i
done

Any pointers would be highly appreciated.

Upvotes: 1

Views: 660

Answers (3)

Chris Johnson
Chris Johnson

Reputation: 21956

It's easy in Python. Put this in /usr/local/bin/pairwise with executable permissions:

#!/usr/bin/env python

from itertools import combinations as combo
import errno
import sys

data = sys.stdin.readlines()

for pair in combo(data, 2):
    try:
        print pair[0].rstrip('\n'), pair[1].rstrip('\n')
    except OSError as exc:
        if exc.errno = errno.EPIPE:
            pass
        raise

Then try this:

seq 4 | pairwise

Resulting in:

1 2
1 3
1 4
2 3
2 4
3 4

Or try this:

for x in a b c d e; do echo $x; done | pairwise

Resulting in:

a b
a c
a d
a e
b c
b d
b e
c d
c e
d e

Upvotes: 0

Adaephon
Adaephon

Reputation: 18339

In zsh you can do the following:

filelist=(*.txt)
for file1 in $filelist; do
    filelist=(${filelist:#$file1})
    for file2 in $filelist; do
        cat "$file1" "$file2" > "${file1%.txt}$file2"
    done
done

Explanation:

Store list of *.txt in filelist, the surrounding parentheses make it an array:

filelist=(*.txt)

Iterate over all elements in filelist for file1:

for file1 in $filelist; do

Remove file1 from filelist:

    filelist=(${filelist:#$file1})

Iterate over the remaining elements in filelist for file2

    for file2 in $filelist; do

Concatenate file1 and file2. Save into new file with combined name (removing .txt from the end of the first file name.)

        cat "$file1" "$file2" > "${file1%.txt}$file2"
    done
done

Upvotes: 2

Raul Andres
Raul Andres

Reputation: 3806

You can solve it by using a simple nested loop

for a in *; do
  for b in *; do
     cat "$a" "$b" > "${a%.txt}$b"
  done
done

You can try too a recursice approach

#!/bin/bash -x

if [ $# -lt 5   ]; then
   for i in *.txt; do
      $0 $* $i;
   done;
else
  name=""

  for i ; do
    name=$name${i%.txt}
  done
  cat $* >> $name.txt
fi;

Upvotes: 2

Related Questions