aboutsummaryrefslogtreecommitdiff
path: root/mgrep
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2015-03-25 15:20:21 +1300
committerTom Ryder <tom@sanctum.geek.nz>2015-03-25 15:20:21 +1300
commitd38da8c2025cc84cf0555d269a6dfccde8294918 (patch)
treea89062226076518c6d58dbc72e9beefb6ec7717b /mgrep
parentInitial commit (diff)
downloadmgrep-d38da8c2025cc84cf0555d269a6dfccde8294918.tar.gz
mgrep-d38da8c2025cc84cf0555d269a6dfccde8294918.zip
Who knows, could be useful for somebody else
Diffstat (limited to 'mgrep')
-rwxr-xr-xmgrep115
1 files changed, 115 insertions, 0 deletions
diff --git a/mgrep b/mgrep
new file mode 100755
index 0000000..13275b3
--- /dev/null
+++ b/mgrep
@@ -0,0 +1,115 @@
+#!/usr/bin/env bash
+
+#
+# GNU grep(1) wrapper to search for fixed patterns in a predefined directory
+# recursively and quickly, intended for interactive use. I wrote this to search
+# my IRC logs in a quick and lazy way, but you could use it for any sort of
+# quick-recursive-grep interactive task, hopefully.
+#
+# "mgrep" is short for "my grep".
+#
+# Author: Tom Ryder <tom@sanctum.geek.nz>
+# Copyright: 2015
+# License: MIT
+#
+self=mgrep
+
+# You will probably want to create an ~/.mgreprc to specify at least the path
+# you want to search, unless it really is $HOME. Here's mine:
+#
+# context=3
+# exclude=$HOME/.mgrep/exclude
+# path=$HOME/Documents/Logs
+#
+# If you want, you can specify different paths by exporting MGREP_CONFIG.
+#
+conf=${MGREP_CONFIG:-$HOME/.${self}rc}
+if [[ -r $conf ]] ; then
+ source -- "$conf"
+fi
+
+# Default to giving three lines of context in grep(1) output
+context=${context:-3}
+
+# Path to filename containing a newline-separated list of exclusion patterns
+# for filenames (not full paths) to be matched by find(1); this file will be
+# silently ignored if nonexistent; bash(1) should raise an error if it exists
+# but isn't readable; defaults to "$HOME"/.local/etc/mgrep/exclude.
+exclude=${exclude:-$HOME/.$self/exclude}
+
+# The path through which find(1) will run to find files for grep(1) to search.
+# Defaults to your $HOME.
+path=${path:-$HOME}
+
+# Start lists of arguments for find(1) and grep(1)
+declare -a find_args grep_args
+
+# Output describing correct usage
+usage() {
+ printf 'Usage: %s [-h|-tN] PATTERN [PATTERN...]\n' \
+ "$self" "$self"
+}
+
+# Look for the -t option, which optionally specifies an -mtime argument to
+# find(1); that is, limit the search to only files modified in the last n days
+while getopts 'ht:' opt ; do
+ case $opt in
+ h)
+ usage
+ exit 0
+ ;;
+ t)
+ find_args=("${find_args[@]}" '-mtime' -"$OPTARG")
+ ;;
+ \?)
+ printf '%s: Invalid option: -%s\n' "$self" "$OPTARG" >&2
+ usage
+ exit 1
+ ;;
+ esac
+done
+shift "$((OPTIND-1))"
+
+# Bail usefully if there are no arguments left; we need at least one
+if ! (($#)) ; then
+ printf '%s: Need at least one argument\n' "$self" >&2
+ usage >&2
+ exit 1
+fi
+
+# Add --regexp patterns to the grep arguments for each command-line argument;
+# this is an OR search, not an AND one, so most of the time you'll probably
+# be specifying just one argument
+for arg in "${@:?}" ; do
+ grep_args=("${grep_args[@]}" '--regexp' "$arg")
+done
+
+# Attempt to read the exclusions file; if it exists, try to read exclusion
+# patterns from it. If it doesn't exist, just continue on.
+if [[ -e $exclude ]] ; then
+ while read -r exclusion ; do
+ if [[ $exclusion ]] ; then
+ find_args=("${find_args[@]}" '!' '-name' "$exclusion")
+ fi
+ done < "$exclude"
+fi
+
+# Try to change into the path for find(1). This is just to prevent long
+# prefixes in the output of `grep -h`.
+cd -- "$path" || exit
+
+# Run the find(1) command with its determined arguments, with an -exec option
+# calling grep(1) with its determined arguments.
+find ./* \
+ -type f \
+ "${find_args[@]}" \
+ -exec \
+ grep \
+ --color=auto \
+ --context="$context" \
+ --dereference-recursive \
+ --ignore-case \
+ --with-filename \
+ "${grep_args[@]}" \
+ {} +
+