3

У меня есть файловая система, которая заполнена, и у меня есть несколько очень больших файлов, которые нужно split (чтобы некоторые из них затем могли быть заархивированы с помощью tar а другие исследованы). Есть ли способ split с поведением "на месте"? Например, мне нужен split -4 file чтобы записать четыре новых файла без использования дополнительного места в файловой системе.

Есть ли способ сделать это?

3 ответа3

2

Это невозможно сделать точно на месте.

Может быть, что-то, что вы можете использовать, - это решение, предложенное в этом ответе:вместо извлечения архива tar

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

Он копирует часть файла в другой файл и немедленно удаляет его из оригинала.

Таким образом, вам нужно только 1 МБ свободного дискового пространства (при условии, что вы разделены на 1 МБ).

РЕДАКТИРОВАТЬ: Если у вас нулевое свободное дисковое пространство, но достаточно оперативной памяти, вы можете создать виртуальный диск и хранить там каждый чанк, пока удаляете исходный чанк. Не проверял это хотя:

ramsize=4096
rammount=/ramdisk
archive="archive.tar"
chunkprefix="$rammount/chunk_"
# 1-Mb chunks :
chunksize=1048576

mkdir $rammount
mkfs -q /dev/ram1 $ramsize
mount /dev/ram1 $rammount

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    # copy the chunk on disk
    cp "$chunkprefix$currentchunk" .
    currentchunk=$((currentchunk-1))
done

Это точно такой же сценарий, за исключением того, что он начинается с создания и монтирования виртуального диска емкостью 4 МБ и временно сохраняет там каждый чанк до тех пор, пока он не освободит место путем усечения исходного файла.

1

Вы можете поэкспериментировать с использованием пространства файловой системы, сопоставленного с памятью (tmpfs), в качестве пространства подкачки для новых файлов до тех пор, пока оригинал не будет удален, что даст вам пространство для перемещения новых файлов обратно на диск. Иногда это /dev /shm или просто /tmp или /var /tmp в зависимости от вашего дистрибутива Linux. Выходные данные mount могут указывать на пространство файловой системы, которое смонтировано в tmpfs

Например, на сервере, который мне пригодился, mount показывает следующее:

tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)

И df -h рассказывает мне об этом /dev/shm

tmpfs                 249M     0  249M   0% /dev/shm

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

0

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

Тем не менее, вы можете использовать dd для чтения раздела файла - для архивации или проверки.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .