Слияние файлов (cat) в каждой папке Unix

Внутри моей основной папки у меня есть несколько подпапок, и каждая подпапка содержит несколько файлов. Я хочу объединить эти файлы в каждой подпапке.

Итак, я пытаюсь сделать что-то вроде этого:

cd ../master-folder

for file in $( find . -name "*.txt" );
do
cat "all the text files in this sub folder" > "name of the subfolder.txt"
rm  "all the previous text files excluding the merged output obviously"
    done

Цените помощь! Спасибо.


person dawnoflife    schedule 22.03.2012    source источник
comment
Важен ли порядок добавления?   -  person paul    schedule 23.03.2012
comment
попробуйте рекурсивный поиск с -exec. потребуется некоторое время, чтобы избежать вуду, но это, вероятно, выполнимо   -  person Not_a_Golfer    schedule 23.03.2012


Ответы (2)


Я бы сделал так, если бы порядок файлов не имел значения:

for i in $(find -maxdepth 1 -mindepth 1 -type d)
do
    find $i -name '*.txt' -type f -exec cat {} >> $i-list.txt \;
    find $i -name '*.txt' -type f -exec rm {} \;
done

Первая находка ищет подкаталоги.

Второй добавляет все содержимое подфайла в файл

Третий удаляет подфайлы.

Это не работает, если есть рекурсивные подкаталоги. Если вы хотите этого, удалите '-maxdepth 1'

person paul    schedule 22.03.2012
comment
Будет ли $i-list включать путь в имя? - person dawnoflife; 23.03.2012
comment
Он будет содержать имя каталога плюс -list.txt. Что вы имеете в виду под дорогой? Просто об этом, если вы используете рекурсивный метод, файл txt будет в родительском каталоге в списке - person paul; 23.03.2012
comment
Я имел в виду имя каталога, извините. - person dawnoflife; 23.03.2012
comment
Не будет ли >> интерпретироваться оболочкой, а не find? - person FatalError; 23.03.2012
comment
>> интерпретируется find (хотя я не уверен, почему) так, как должно. Проблема возникает из-за пробела, который я забыл между {} и \; при последней находке. Должно быть {} \; - person paul; 23.03.2012
comment
@Paul Да, ты прав. Должно быть, это не соответствует грамматике оболочки, и find (по крайней мере, вариант GNU в моем случае) достаточно умен, чтобы справиться с этим. Аккуратный! - person FatalError; 23.03.2012
comment
Я думаю, что >> на самом деле интерпретируется bash. find должен вывести все cat на стандартный вывод, а затем bash перенаправит все в файл. Доказательство в том, что find >> $i-list.txt $i -name '*.txt' -type f -exec cat {} \; работает. - person paul; 23.03.2012

Почему бы не посещать каждый каталог рекурсивно? Что-то вроде:

#!/bin/bash                                                                     

shopt -s nullglob # Make failed globs expand to nothing

function visit {
    pushd "$1"
    txts=(*.txt)
    if ((${#txts[@]} > 0))
    then
        cat "${txts[@]}" > "${PWD##*/}.txt"
        rm -f "${txts[@]}"
    fi
    for dir in */
    do
        visit "$dir"
    done
    popd
}

visit /path/to/start/dir

Предостережение: если у вас есть символические ссылки, которые создают циклы в вашем дереве каталогов, то это плохая идея.

person FatalError    schedule 22.03.2012