2014-02-13 5 views
0

Я хотел бы конкатенировать существующие .txt-файлы в каталоге попарно. Сопоставляя все возможные комбинации исходных файлов. Я не уверен, как это сделать, используя bash или zshshell scripting, не совсем мой сильный костюм. Думаю, нужно было бы выводить новые файлы в другой каталог, предотвращая экспоненциальное увеличение комбинаций.присоединяет файлы попарно.

Ниже приведен фиктивный пример. На самом деле у меня больше файлов.

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

где A + B такая же, как B + A и порядок не имеет значения.

Желаемый результат:

>ls 
AB.txt AC.txt BC.txt 

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

Ниже попытка (на что-то ...)

#!/bin/zsh 

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

Все указатели будут высоко оценены.

+0

У вас уже есть файлы? Или вы хотите, чтобы они были созданы? –

+0

Я их уже создал. –

+0

Ваши примеры не соответствуют вашим вопросам: вы говорите, что хотите объединить свои файлы, но ваш образец вывода выглядит так, будто вы хотите объединить строки входных файлов вместе. Что это такое и откуда берется «#»? Кроме того, кажется, что для ваших целей 'A.txt + B.txt' совпадает с' B.txt + A.txt'. Правильно ли это предположение? Если да, важно ли, чтобы файл был первым? – Adaephon

ответ

1

В zsh вы можете сделать следующее:

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

Пояснение:

список Магазин *.txt в filelist, окружающие скобки делают массив:

filelist=(*.txt) 

перебрать все элементы в filelist для file1:

for file1 in $filelist; do 

Удалить file1 из filelist:

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

Итерация над остальными элементами в filelist для file2

for file2 in $filelist; do 

конкатенации file1 и file2. Сохранить в новый файл с именем комбинированного (удаление .txt с конца первого имени файла.)

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

Вы можете решить с помощью простого вложенного цикла

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

Вы можете попробовать тоже recursice подход

#!/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; 
+0

Спасибо, что комментировали. Если у меня есть, например, 100 файлов в каталоге, я думаю, мне нужно было бы иметь 99 вложенных циклов? Я уточнил свой вопрос. –

+1

Если у вас есть 100 файлов в каталоге, и вы хотите объединить их в любой возможной позиции, вам понадобится больше диска, чем у Google –

+0

Я вижу вашу мысль. Но возможно ли добиться того же результата, но без необходимости выполнять вложенные циклы? –

0

Это легко в Python.Поместите это в /usr/local/bin/pairwise с разрешениями исполняемым:

#!/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 

Тогда попробуйте это:

seq 4 | pairwise

Результирующее в:

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

Или попробуйте это:

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

Результирующий сайт:

a b 
a c 
a d 
a e 
b c 
b d 
b e 
c d 
c e 
d e 
Смежные вопросы