LINUX.ORG.RU

Как разбить файл на несколько а потом собрать?

 ,


0

1

Дано, файл контейнер 20ГБ, нужно разбить его на N файлов разной длинны, где длинна выходных файлов указывается в диапазоне например от 100М до 500M и послений отрезок, если он не подпал под условие 100500 пишется как есть. Затем, зная последовательность разбивки, нужно это всё склеить так чтобы контрольные суммы до и после сошлись.

Думаю можно сделать dd, но как заставить dd писать каждый новый файл с места где была прервана запись предыдущего?

Правда dd не хотелосьбы т.к. любит он ОЗУ, во всяком случае при чтении из urandom.

UDP1: ключ skip у dd позволяет пропускать заданое количество блоков, выходит можно размер в байтах основного файла побить на куски, требуемым алгоритмом и потом складывая размер уже скопированных частей нарезать следующие.

UPD2: ключ conv=notrunc у dd позволяет дописывать из if в of.

Ответ на: комментарий от Paramushir

Покажит пожалуйста, как сделать многотомный архив тома которого будут иметь разный размер.

ты каким архиватором предпочитаешь пользоваться? образ уже готовый или тебе прямо сейчас его надо снять?

justAmoment ★★★★★ ()

Написал скриптег, размер пересобранного контейнера совпадает но не совпадает контрольная сумма.

#!/bin/bash

rm -f /tmp/*\.part > /dev/null 2>&1

fileSize=`du -b $1  | awk '{print $1}'`
echo "Before"
echo $fileSize
md5sum $1
remain=$fileSize
minSize=500000
maxSize=1000000
sizesP=()
sum=0
while true
do
        sizePart=`shuf -i $minSize-$maxSize -n 1`
        if [ $sizePart -gt $remain ]; then
                sizesP+=("$remain")
                for sizeP in ${sizesP[@]}
                do
                        #echo $sizeP
                        dd if=$1 of=$sizeP.part skip=$sum iflag=skip_bytes > /dev/null 2>&1
                        sum=$(($sum+$sizeP))
                done
                echo $sum
                break
        else
                remain=$(($remain-$sizePart))
                sizesP+=("$sizePart")
        fi
done

# Клеим
if [ -d /tmp/kk/ ]; then
        if [ -f /tmp/kk/test ]; then
                rm -f /tmp/kk/test
        else
                sleep 0
        fi
else
        mkdir /tmp/kk/
fi

for sizeP in ${sizesP[@]}
do
        dd if=$sizeP.part of=/tmp/kk/test conv=notrunc > /dev/null 2>&1
done
echo "After"
du -b /tmp/kk/test  | awk '{print $1}'
md5sum /tmp/kk/test
exit 0

Before
10485760
e6fe5f7625d3423606915be815d80c73  /tmp/test
10485760
After
10485760
>6d0ccdd49e3359ceec5f632141dd79e5  /tmp/kk/test

Где косяк? Спойлер не получился.

Paramushir ()
Ответ на: комментарий от Paramushir

Разный размер? Вот вообще разный? Можно так:

< файл tail -c +1 | head -c размер1 > фрагмент1
< файл tail -c +$((1+размер1)) | head -c размер2 > фрагмент2
< файл tail -c +$((1+размер1+размер2)) | head -c размер3 > фрагмент3

Можно то же самое сделать на dd.

Сборка банальным cat фрагмент*.

legolegs ★★★★★ ()
Ответ на: комментарий от Paramushir

Починил.

                        dd if=$1 of=$sizeP.part skip=$sum iflag=skip_bytes > /dev/null 2>&1

меняем на

                        dd if=$1 of=$sizeP.part skip=$sum > /dev/null 2>&1

Т.е. ты не знаешь что тебе нужно?

Я разве об этом писал где-то? А так, денег много и паспортов.

Paramushir ()