Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: edb6e2646a
Fetching contributors…

Cannot retrieve contributors at this time

executable file 77 lines (66 sloc) 2.18 kB
#!/bin/bash
# search disk for a string and output commands to dump matching sections
# Author:
# http://www.pixelbeat.org/
# Notes:
# On my Fedora 8 system members of the "disk" group are
# allowed to read the disk devices, so to do that:
# sudo /usr/sbin/usermod -a -G "disk" $USER
# sudo su - $USER
# Changes:
# V0.1, 20 Apr 2008, Initial release
# V0.3, 29 Sep 2010
# http://github.com/pixelb/scripts/commits/master/scripts/disk_grep
usage() {
echo "Usage: $(basename $0) file|device string" >&2
exit 1
}
COLUMNS=$(tput cols)
#pass % complete
progress() {
DONE=$(( (($COLUMNS-2)*$1)/100 ))
TODO=$(($COLUMNS-2-$DONE))
DONE=$(printf "%${DONE}s" | tr ' ' =)
TODO=$(printf "%${TODO}s" | tr ' ' -)
printf "[$DONE$TODO]\r" > /dev/tty
}
#pass strings to stdout
print() {
CLEAR=$(printf "%${COLUMNS}s")
printf "$CLEAR\r"
echo "$@"
}
[ $# -ne 2 ] && usage
DISK="$1"
STRING="$2"
export LANG=C
# Note we must manage these limits ourselves
# because dd currently does not fail if you seek
# past the end of a file or device. In fact for devices
# it reads the whole device when you do this!
#
# This also allows us to show completion progress
CHUNK_SIZE=$((8*1024*1024))
if [ -b "$DISK" ]; then
SIZE=$(/sbin/blockdev --getsize64 $DISK) || exit $? #reads from disk?
else
SIZE=$(stat --format %s "$DISK") || exit $?
fi
[ $SIZE -eq 0 ] && exit
CHUNKS=$((($SIZE+$CHUNK_SIZE-1)/$CHUNK_SIZE))
i=0
while true; do
progress $(($i*100/$CHUNKS))
[ "$i" -ge "$CHUNKS" ] && break
# use "direct" flag so cache not polluted with read data
dd if=$DISK iflag=direct conv=noerror bs=$CHUNK_SIZE count=1 skip=$i 2>/dev/null |
#we ensure grep reads all data, otherwise dd will get SIGPIPE and exit with 141
grep --binary-files=text -U -F "$STRING" >/dev/null
status=$(echo ${PIPESTATUS[@]})
dd_status=$(echo $status | cut -f1 -d ' ')
re_status=$(echo $status | cut -f2 -d ' ')
[ $dd_status -ne 0 ] && { echo "dd error" >&2; exit $dd_status; }
[ $re_status -eq 0 ] && { print "dd if=$DISK iflag=direct bs=$CHUNK_SIZE count=1 skip=$i > disk_grep.$i"; }
i=$(($i+1))
done
echo
Jump to Line
Something went wrong with that request. Please try again.