使用 bash 脚本从二进制闪存映像的末尾删除 0xff

Remove 0xff from the end of a binary flash image using bash script

我有一个工具可以生成要写入闪存的 32MB 二进制映像。 但是只有前 2MB 包含有价值的数据,其余的只是 0xff。 所以我想使用一个很好的 bash / makefile 脚本从文件末尾删除 0xff 字节。 我可以使用 head:

head -c 2M test.bin > out.bin

但我不知道实际长度,所以我想从文件末尾找到第一次出现的 0xff 作为 head 或类似的输入。

我是 运行 我的工具,来自 cygwin 上的 Makefile,所以如果可以使用标准 bash / makefile 工具执行它会很好。

这个 sed one liner 将只对文件的最后一行进行操作,并删除所有尾随 0xFF 字节。

sed '$ s/\xff*$//' file > file.out
head -c -1 test.bin > out.bin

-1 去掉最后一个字节。

计算文件末尾的 0xFF 字节数可以使用 hexdump(或 xxdod...)的组合来完成将二进制文件转换为 ASCII 十六进制值流和 awk 这样的文本处理器来进行计数。示例:

hexdump -v -e '/1 "%02X\n"' test.bin | \
  awk '/FF/ {n += 1} !/FF/ {n = 0} END {print n}'

然后,可以使用例如从文件末尾删除该字节数ddhead。示例:

head -c -$d test.bin > results/test.bin

总而言之,您的 Makefile 可能类似于:

OUTDIR  := results
OLDBINS := $(wildcard *.bin)
NEWBINS := $(addprefix $(OUTDIR)/,$(OLDBINS))

.PHONY: all

all: $(NEWBINS)

$(OUTDIR)/%: % | $(OUTDIR)
    n=$$(hexdump -v -e '/1 "%02X\n"' $< | \
      awk '/FF/ {n += 1} !/FF/ {n = 0} END {print n}'); \
    head -c -$$n $< > $@

$(OUTDIR):
    mkdir -p $@

有一些 make 的细微之处,例如 phony targets ( all), automatic variables ($<, $@), order-only prerequisites (| $(OUTDIR))、在配方中进行扩展转义($$ 符号)、make 函数(wildcardaddprefix),一个使用续行的单行配方(行尾的 \)...但没有什么很复杂的。

编辑:尝试找到更快的解决方案:

如果 base64 实用程序可用并且文件大小恰好是 32MB,则另一个选项可能更有效(在我的超级简单测试中,32MB 文件的速度大约快 20 倍):

  1. base64-不换行编码:

     base64 -w0
    
  2. 使用 sed 删除所有尾随的 //// 字符串,然后是文件末尾的最后一个 //8=(参见 the base64 RFC 4648)理解为什么这些奇怪的尾随文本:

     sed -E 's#(////)*//8=$##'
    
  3. base64-解码:

     base64 -d
    

一行:

base64 -w0 test.bin | sed -E 's#(////)*//8=$##' | base64 -d > results/test.bin

请注意,这可能会在文件末尾留下一两个 0xFF 个字符,具体取决于输入文件的大小和尾随 0xFF 个字符的数量。新的配方是:

$(OUTDIR)/%: % | $(OUTDIR)
    base64 -w0 $< | sed -E 's#(////)*//8=$$##' | base64 -d > $@