Basicamente, o que você precisa é a possibilidade de inserir o arquivo no alcatrão e "cortar" a frente à medida que avança.
No StackOverflow, alguém perguntou como truncar um arquivo na frente , mas parece que não é possível. Você ainda pode preencher o início do arquivo com zeros de uma maneira especial, para que o arquivo se torne um arquivo esparso , mas não sei como fazer isso. No entanto, podemos truncar o final do arquivo. Mas o tar precisa ler o arquivo para a frente, não para trás.
Solução 1
Um nível de indireção resolve todos os problemas. Primeiro inverta o arquivo no local, depois leia-o para trás (o que resultará na leitura do arquivo original para a frente) e trunque o final do arquivo invertido à medida que avança.
Você precisará escrever um programa (c, python, qualquer que seja) para trocar o início e o final do arquivo, pedaço por pedaço, e depois canalizar esses pedaços para tar, enquanto trunca o arquivo um pedaço por vez. Essa é a base da solução 2, que talvez seja mais simples de implementar.
Solução 2
Outro método é dividir o arquivo em pequenos pedaços no local e excluí-los à medida que os extraímos. O código abaixo tem um tamanho de bloco de um megabyte, ajuste de acordo com suas necessidades. Maior é mais rápido, mas ocupa mais espaço intermediário ao dividir e durante a extração.
Divida o arquivo archive.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
Canalize esses arquivos no tar (observe que precisamos da variável chunkprefix no segundo terminal):
mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.
Como usamos um pipe nomeado ( mkfifo fifo), você não precisa canalizar todos os pedaços de uma só vez. Isso pode ser útil se você estiver realmente com pouco espaço. Você pode seguir as seguintes etapas:
- Mova, digamos os últimos blocos de 10 GB para outro disco,
- Comece a extração com os pedaços que você ainda tem,
- Quando o
while [ -e … ]; do cat "$chunk…; doneloop terminar (segundo terminal):
- NÃO pare o
tarcomando, NÃO remova o fifo (primeiro terminal), mas você pode executar sync, por precaução,
- Mova alguns arquivos extraídos que você sabe que estão completos (o tar não está parado aguardando a conclusão dos dados para extrair esses arquivos) para outro disco,
- Mova os pedaços restantes para trás,
- Continue a extração executando as
while [ -e … ]; do cat "$chunk…; donelinhas novamente.
É claro que tudo isso é de alta tensão , você deve verificar primeiro se tudo está bem em um arquivo fictício, porque se você cometer um erro, adeus aos dados .
Você nunca saberá se o primeiro terminal ( tar) realmente terminou o processamento do conteúdo do fifo; portanto, se preferir, execute isso em vez disso, mas não terá a possibilidade de trocar facilmente pedaços com outro disco:
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
currentchunk=$((currentchunk+1))
done | tar -xf -
aviso Legal
Observe que, para que tudo isso funcione, seu shell, cauda e truncado devem manipular números inteiros de 64 bits corretamente (você não precisa de um computador de 64 bits nem de um sistema operacional para isso). O meu funciona, mas se você executar o script acima em um sistema sem esses requisitos, perderá todos os dados em archive.tar .
E, em qualquer caso, algo que não dê errado, você perderá todos os dados em archive.tar de qualquer maneira, portanto, certifique-se de ter um backup dos seus dados.