
Представьте себе файл, созданный с помощью:
truncate -s1T file
echo test >> file
truncate -s2T file
Теперь у меня есть файл размером 2 терабайта (занимающий 4 КБ на диске), "test\n"
в середине которого написано:
Как бы мне восстановить это "test"
эффективно, не читая весь файл?
tr -d '\0' < file
Дал бы мне результат, но это заняло бы часы.
Мне бы хотелось, чтобы выводились только неразреженные части файла (то есть только вышеуказанный "test\n"
или, что более вероятно, блок размером 4 КБ, выделенный на диске, в котором хранятся эти данные).
Существуют API, позволяющие узнать, какие части файлавыделено(FIBMAP, FIEMAP, SEEK_HOLE, SEEK_DATA...), но какие инструменты их раскрывают?
Было бы желательно иметь портативное решение (по крайней мере для ОС, поддерживающих эти API).
решение1
Лучшее, что мне удалось придумать на данный момент (ksh93, начиная filefrag
с e2fsprogs
версии 1.42.9 (некоторые старые версии имеют другой API), на файловых системах на основе экстентов в 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
сообщает об экстентах файла с помощью FIEMAP ioctl для файловых систем, которые его поддерживают.
Эта *unwritten*
часть охватывает файлы (неразреженные, но все еще заполненные нулями, которые мне не интересны), которые были записаны, fallocated
но в которые не производилась запись.
Последние версии bsdtar
или star
могут использовать некоторые из этих API для генерации tar
файла, который идентифицирует разреженные разделы как таковые. Это сделало бы для болеепортативныйрешение, но тогда придется анализировать сгенерированный tar-файл, чтобы получить неразреженные разделы.