Reputation: 3512
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
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
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
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