Como eu divido arquivos no lugar (delete original como novos arquivos são escritos)

3

Eu tenho um sistema de arquivos que está cheio e eu tenho vários arquivos muito grandes que precisam ser split (para que alguns deles possam ser arquivados com tar e os outros examinados). Existe uma maneira de split com um tipo de comportamento "no local"? Por exemplo, eu preciso de split -4 file para escrever os quatro novos arquivos sem usar nenhum espaço adicional no sistema de arquivos.

Existe uma maneira de fazer isso?

    
por CHK 09.07.2013 / 20:40

3 respostas

2

Não é possível fazer isso exatamente no lugar.

Talvez algo que você possa usar seja a solução sugerida nesta resposta: No local, extraia o arquivo 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

O que ele faz é copiar uma parte do arquivo em outro arquivo e excluí-lo imediatamente do original.

Desta forma, você só precisa de 1MB de espaço livre em disco (supondo que você tenha dividido em 1MB).

EDITAR: Se você tiver zero de espaço livre em disco, mas tiver memória suficiente, poderá criar um disco virtual e armazenar cada parte enquanto exclui o bloco original. Ainda não testou:

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

É exatamente o mesmo script, exceto que ele começa criando e montando um disco RAM de 4 MB e armazena temporariamente cada fragmento até que libere espaço truncando o arquivo original.

    
por 10.07.2013 / 01:15
1

Você pode experimentar o uso do espaço do sistema de arquivos que é mapeado na memória (tmpfs) como um espaço de troca para os novos arquivos até que o original seja excluído, oferecendo espaço para mover os novos arquivos de volta para o disco. Às vezes, isso é / dev / shm ou apenas / tmp ou / var / tmp dependendo da sua distribuição do Linux. A saída do mount pode indicar a você um espaço no sistema de arquivos que é montado no tmpfs

Por exemplo, em um servidor que eu tinha à mão, o mount revela isso:

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

E df -h me informa sobre /dev/shm

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

Nota: se você sobrecarregar este espaço, você afetará outros processos que precisam de memória para rodar bem, incorrerá em swap para trocar espaço no HDD, o que aumenta o tempo de troca de contexto da CPU já que tem que carregar esse material de volta para a memória quando esse processo recebe ciclos de CPU.

    
por 16.07.2013 / 06:41
0

Eu não acho que isso é possível porque um arquivo usa um ou vários blocos , então se você quiser dividir não no limite do bloco, você precisará mover o resto do arquivo para que começa no começo de um bloco.

No entanto, você pode usar dd para ler uma seção de um arquivo - para arquivar ou examinar.

    
por 09.07.2013 / 20:51