forked from pixelb/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdisk_grep
More file actions
executable file
·77 lines (67 loc) · 2.15 KB
/
disk_grep
File metadata and controls
executable file
·77 lines (67 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/bin/bash
# search disk for a string and output commands to dump matching sections
# License: LGPLv2
# 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