I'm trying to find the first non-zero byte (starting from an optional offset) on a block device using dd
and print its offset, but I am stuck. I didn't mention dd
in the title as I figured there might be a more appropriate tool than dd
to do this, but I figured dd
should be a good start. If you know of a more appropriate tool and/or more efficient way to reach my goal, that's fine too.
In the meantime I'll show you how far I've come with dd
in bash, so far.
#!/bin/bash
# infile is just a temporary test file for now, which will be replaced with /dev/sdb, for instance
infile=test.txt
offset=0
while true; do
byte=`dd status='none' bs=1 count=1 if="$infile" skip=$offset`
ret=$?
# the following doesn't appear to work
# ret is always 0, even when the end of file/device is reached
# how do I correctly determine if dd has reached the end of file/device?
if [ $ret -gt 0 ]; then
echo 'error, or end of file reached'
break
fi
# I don't know how to correctly determine if the byte is non-zero
# how do I determine if the read byte is non-zero?
if [ $byte ???? ]; then
echo "non-zero byte found at $offset"
break
fi
((++offset))
done
As you can see, I'm stuck with two issues that I don't know how to solve:
a. How do I make the while
loop break
when dd
has reached the end of the file/device? dd
gives an exit code of 0
, where I expected a non-zero exit code instead.
b. How do I evaluate whether the byte that dd
read and returns on stdout is non-zero? I think I've read somewhere that special care should be taken in bash with \0
bytes as well, but I'm not even sure this pertains to this situation.
Can you give me some hints on how to proceed, or perhaps suggest and alternative way to achieve my goal?
dd
then either read the file a byte at a time or perhaps use something likecut
to detect the null (zero) byte(s) otherwise known as\n
. Might be necessary to prefill your file with non-null bytes.$byte
, except if it's a newline (which command substitution removes), or a NUL (which Bash treats as end of string). In those cases you'd get an empty variable, and I don't think there's any way to tell them apart in just Bash.dd
per byte of input, so it'll be horribly slow. Well, (apart from the issues with NUL and newline), you could read larger blocks and process the string one byte at a time, but really, you'd be better off just taking an actual programming language more suited for data processing.