Командная строка для обратного байта/изменения 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