Как удалить/вырезать нули/нулевые байты из файла

Как удалить/вырезать нули/нулевые байты из файла

Дано: общий двоичный файл и размер блока

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

Мне действительно интересно, почему я не могу найти инструмент, который делает эту простую работу. Я создал небольшой скрипт, но его производительность смехотворна. Должно же быть существующее программное обеспечение, способное сделать это, не так ли?!

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

Редактировать: поток sed, о котором вы говорите, заменяет каждый байт, я просто хочу заменить 0 байтов, если их идет по крайней мере столько же, сколько и блоков подряд.

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

EDIT 2: Размер файла составляет порядка 10-1000 ГБ. Для небольших размеров мой медленный собственный инструмент подходит, но для таких больших файлов ...

решение1

bbeэто " sedподобный редактор для двоичных файлов". В Debian он находится в bbeпакете.

Было бы лучше, если бы вы могли s/^\0*$//определить блоки, полные нулевых байтов, и удалить их. Мои тесты показывают, что такие выражения, подобные регулярным выражениям, не работают в bbe. Вы все равно можете использовать (почти) столько, \0сколько вам нужно:

s/\0\0…\0\0//

где обозначает правильное количество \0подстрок. Если вы выберете большой размер блока, то может быть проблематично передать соответственно длинную строку через командную строку. К счастью, bbeподдерживает чтение скрипта из файла. Действуйте так:

# The following function uses non-POSIX 'for' loop. Rewrite if necessary.
gen_script() {
   printf 's/'
   for ((i=0;i<"$1";i++)); do
      printf '\\0'
   done
   printf '//\n'
}

# This needs to be a plain decimal number:
blocksize=512

gen_script "$blocksize" > bbe-script
<binary_file_in bbe -b ":$blocksize" -f bbe-script >binary_file_out

Проблемы:

  1. Приведенная выше реализация gen_scriptдовольно медленная и непрактичная для больших blocksize.
  2. В моих тестах bbeвел себя неправильно для blocksizeболее чем 16384(т.е. блоков по 16 КиБ). Это делает первую проблему неактуальной.
  3. В этой роли bbeсам по себе тоже не очень быстрый. Я не знаю, насколько велик ваш "очень большой файл". Если бы я был вами, я бы попробовал

    pv binary_file_in | bbe -b ":$blocksize" -f bbe-script >binary_file_out
    

    и через несколько секунд я смогу сказать, приемлемо ли расчетное время прибытия.

Связанный контент