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

使用bash脚本从二进制闪存映像的末尾删除0xff,bash,makefile,cygwin,binaryfiles,Bash,Makefile,Cygwin,Binaryfiles,我有一个工具,可以生成一个32MB的二进制图像写入闪存。 但只有前2MB包含有价值的数据,其余仅为0xff。 因此,我想使用一个漂亮的bash/makefile脚本从文件末尾删除0xff字节。 我可以用头: head -c 2M test.bin > out.bin 但是我不知道实际的长度,所以我想找到从文件末尾第一次出现的0xff,作为输入到head或类似文件 我是从cygwin上的Makefile运行我的工具,因此如果可以使用标准的bash/Makefile工具来执行,那就太好了。这

我有一个工具,可以生成一个32MB的二进制图像写入闪存。 但只有前2MB包含有价值的数据,其余仅为0xff。 因此,我想使用一个漂亮的bash/makefile脚本从文件末尾删除0xff字节。 我可以用头:

head -c 2M test.bin > out.bin
但是我不知道实际的长度,所以我想找到从文件末尾第一次出现的0xff,作为输入到head或类似文件


我是从cygwin上的Makefile运行我的工具,因此如果可以使用标准的bash/Makefile工具来执行,那就太好了。

这个sed one liner将只在文件的最后一行运行,并删除所有尾随的
0xFF
字节

sed '$ s/\xff*$//' file > file.out

-1去除最后一个字节。

计算文件末尾的
0xFF
字节数可以通过组合
hextdump
(或
xxd
od
…)将二进制文件转换为ASCII十六进制值流,并使用类似
awk
的文本处理器进行计算。例如:

hexdump -v -e '/1 "%02X\n"' test.bin | \
  awk '/FF/ {n += 1} !/FF/ {n = 0} END {print n}'
head -c -$d test.bin > results/test.bin
然后,可以使用例如
dd
head
从文件末尾删除该数量的字节。例如:

hexdump -v -e '/1 "%02X\n"' test.bin | \
  awk '/FF/ {n += 1} !/FF/ {n = 0} END {print n}'
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 $@
  • 使用
    sed
    删除所有尾随的
    //
    字符串,然后在文件末尾添加最后一个
    //8=
    (请参阅),以了解这些奇怪的尾随文本的原因:

    sed -E 's#(////)*//8=$##'
    
  • 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 > $@
    
    $(OUTDIR)/%:%|$(OUTDIR)
    base64-w0$<| sed-E的#(//)*///8=$$##'| base64-d>$@
    
    您的有效数据中是否存在
    0xff
    ,或者您是否确定它仅存在于最后~30 MB中?使用
    dd
    并仅复制前2MB数据有什么问题?该文件可以是2MB到4MB之间的任何文件。4MB在我相对较慢的设备上编程需要更长的时间。它的开头和中间可以包含0xff,应该保持不变。在二进制文件上使用文本编辑器sed并不是那么简单。你的建议不符合要求。例如,如果一系列
    0xff
    字节后跟一个行尾,它将删除这些字节,即使它们不在文件的末尾。使用此选项很可能会损坏一些二进制文件…恐怕你错了。这将完全满足任何文件的要求。它将只删除尾随的0xff字节,而不考虑文件的其他原始内容。我对此进行了明确的测试,我正在用这些测试更新我的答案,这些测试表明它可以按预期工作。它在最初的100k字节中工作得非常好,但在此之后,它开始删除0xff的单个出现,并更改字节顺序!试图弄清楚sed脚本到底做了什么,但也许你可以解释一下。在hextump之后,我得到了以下区别:Before:009dd00 0000 f840 45b2 ff2f 9f0a 0e47 0000 0000 After:009dd00 0000 f840 45b2 0a2f 479f 000e 0000 000hmm,我想我刚才添加到解决方案中的测试没有我想象的那么健壮。我将在一个大得多的文件上尝试这个…我在一个大得多的文件上尝试了这个,并确认它是有效的。我拿了我在示例中提到的文件,一遍又一遍地重复它,直到有一个285570字节的文件,后面有0xff字节。然后我手动删除了尾随的字节,并获取md5sum。最后,我使用sed脚本删除字节,并使用md5sum确认文件是相同的。你确定你正确地编写了sed命令吗?head不是一个用于二进制对象的工具,而且他要求删除所有字节而不仅仅是oneOops,我没有注意到他明确地说要删除所有字节。除此之外,
    head
    为什么不能与不一定包含行终止符的文件一起使用?我在
    head
    手册页中没有看到任何此类限制,我会得出结论,-c选项应该适用于所有类型的文件。这似乎满足了我的需要。但是因为你看起来很感兴趣,所以速度很慢,我的32MB文件需要25秒。第一个sed解决方案大约在1s内执行。但这对我来说没关系。非常感谢你的帮助!我对它的速度很慢并不感到惊讶,老实说,就我个人而言,我会编写一个小的C或python程序来更快地完成同样的工作。由于从二进制到十六进制的转换以及
    awk
    逐字节计数,因此速度较慢。也许有人会提供一个更快的解决方案,但如果你坚持使用标准的shell实用程序,我并不期待奇迹出现。请注意,如果速度是一个问题,并且你有一台多核计算机,我建议的Makefile是并行安全的。例如,在一台4核计算机上以
    make-j4
    的方式运行它,其加速度几乎是4倍。此外,依赖关系的表达是正确的:如果输入文件没有更改,则在下次调用make时不会重新生成输出文件。您尝试更快的解决方案的速度实际上较慢,在我的32MB文件上花费了37秒。哎呀,我的计算机上只花了0.4秒。。。嗯,这可能是因为我们的计算机之间存在显著差异(可能是内存)。顺便问一下,关于您的输入文件,您确定知道什么?从你的问题看不太清楚。它们的大小是否固定为32MB?您是否已经确定要保留的零件的最大尺寸?这可能被有效地用来加速整个过程。