使用bash脚本从二进制闪存映像的末尾删除0xff
我有一个工具,可以生成一个32MB的二进制图像写入闪存。 但只有前2MB包含有价值的数据,其余仅为0xff。 因此,我想使用一个漂亮的bash/makefile脚本从文件末尾删除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工具来执行,那就太好了。这
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?您是否已经确定要保留的零件的最大尺寸?这可能被有效地用来加速整个过程。