
Imagine um arquivo criado com:
truncate -s1T file
echo test >> file
truncate -s2T file
Agora tenho um arquivo de 2 tebibytes (que ocupa 4kiB no disco), "test\n"
escrito no meio.
Como eu recuperaria isso de "test"
forma eficiente, sem precisar ler o arquivo inteiro.
tr -d '\0' < file
Me daria o resultado, mas isso levaria horas.
O que eu gostaria é de algo que produza apenas as partes não esparsas do arquivo (acima apenas "test\n"
ou mais provavelmente, o bloco de 4kiB alocado no disco que armazena esses dados).
Existem APIs para descobrir quais partes do arquivo estãoalocado(FIBMAP, FIEMAP, SEEK_HOLE, SEEK_DATA...), mas quais ferramentas os expõem?
Uma solução portátil (pelo menos para os sistemas operacionais que suportam essas APIs) seria apreciada.
Responder1
O melhor que consegui até agora é (ksh93, usando filefrag
1.42.9 e2fsprogs
(algumas versões mais antigas têm uma API diferente), em sistemas de arquivos baseados em extensão no Linux):
#! /bin/ksh93 -
export LC_ALL=C
for file do
filefrag -vb1 -- "$file" |
while IFS=": ." read -A a; do
[[ $a = +([0-9]) ]] && [[ ${a[@]} != *unwritten* ]] &&
command /opt/ast/bin/head -s "${a[1]}" -c "${a[7]}" -- "$file"
done
done
filefrag
relata as extensões do arquivo usando o ioctl FIEMAP para os sistemas de arquivos que o suportam.
A *unwritten*
parte cobre os arquivos (não esparsos, mas ainda cheios de zeros nos quais não estou interessado) que foram gravados, fallocated
mas não foram gravados.
Versões recentes bsdtar
ou star
podem usar algumas dessas APIs para gerar um tar
arquivo que identifica as seções esparsas como tal. Isso daria maisportátilsolução, mas seria necessário analisar o arquivo tar gerado para obter as seções não esparsas.