Командная строка для обратного байта/изменения endianess
Я разбираюсь в некоторых сценариях, пытаясь разобрать некоторые данные, написанные Javas DataOutputStream#writeLong(...)
. Поскольку java всегда, кажется, пишет большой endian, у меня есть проблема с подачей байтов в od
. Это связано с тем фактом, что od
всегда предполагает, что endianess соответствует завершенности арки, в которой вы сейчас находитесь, и я нахожусь на маленькой конечной машине.
Я ищу простой однострочный инструмент для изменения порядка байтов. Скажем, что вы знаете, что последние 8 байтов файла длинны, написанные вышеупомянутым методом writeLong(...)
. Моя самая лучшая попытка напечатать эту длинную версию
tail -c 8 file | tac | od -t d8
но tac
работает только по тексту (достаточно справедливо). Я нашел несколько ссылок на dd conv=swab
, но это только свопирует байты в парах и не может отменить эти восемь байтов.
Кто-нибудь знает хороший однострочный для этого?
Ответы
Ответ 1
В конце концов, прибегает к Perl. Использовал один слой, который я нашел в PERL One Liners:
tail -c 8 file | perl -0777e 'print scalar reverse <>' | od -t d8
Разделитель 0777
char был немного озадачен для меня, но эта страница в debian admin, по-видимому, предполагает, что он является заполнителем для "никакой записи разделитель", вызывая полный обратный байт за байт.
Другие предложения приветствуются.
EDIT: Найдена другая команда в комментарии к tac.c, которую я загрузил из GNU coreutils:
Скопируйте каждый FILE или стандартный ввод, если ни один не указан, или когда Имя ФАЙЛА "-" встречается на стандартном выходе с помощью порядок обращений. Записи разделяются экземпляров строки или новой строки, если ни один не указан. По умолчанию строка разделителя прикреплена к концу записи, чтобы она следует в файле.
Параметры: -b, - before Разделитель прикреплен к началу записи, которую он предшествует в файле. -r, --regex Сепаратор является регулярным выражением. -s, --separator = separator Используйте SEPARATOR в качестве разделителя записей.
Чтобы отменить байты файла байтом, используйте (в bash, ksh или sh): tac -r -s '.\| 'file
Ответ 2
Вы можете использовать objcopy:
$ objcopy -I binary -O binary --reverse-bytes=num inputfile.bin outputfile.bin
где num - либо 2, либо 4.
Ответ 3
Обратите внимание, что следующая версия GNU coreutils ( >= 8.23) добавит параметр -endian = {little, big} в команду od
Ответ 4
Я придумал этот однострочный Perl для преобразования 4-байтовых целых чисел из одной континентности в другую:
$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin > littlend.bin
Это, вероятно, отлично работает на реальных машинах Linux, но Cygwin немного покончил с собой, рассматривая двоичный файл как текст и вставляя 0x0D (aka CR) перед каждым байтом 0x0A (aka newline). Но если вы подключаетесь к cat -
, это, кажется, оставляет его в покое. Это работает для меня:
$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin | cat - > littlend.bin
Ответ 5
BASH:
od -b -v -w8 | while read pfx b8 ; do [ "$b8" ] && echo -n 12345678 | tr 87654321 \\${b8// /\\} ; done
Чтобы быть немного более надежным в зависимости от стиля вывода od
, может потребоваться сжать пробелы (вставить "| sed 's/ */ /g'"
после w8
).
Ответ 6
Используется dd, Luke!
dd if=sourcefile of=resultfile conv=swab