Mastodon

Opening the results of a grep in Vim

This week while removing some deprecated syntax from our old tests I found myself wondering how to take the results of my grep command and open the files returned in vim. Moments like this are great for getting to know your tools better so I decided to figure it out. Opening the files was not that difficult to figure out:

vim -o `grep -ril Factory.build test/`

This did exactly the right thing, a case insensitive (-i), recursive (-r) search of the test directory for the problematic syntax (Factory.build) returning only filenames (-l) and then opening the results in vim. I was able to quickly make my changes with a search and replace. With that done you can then write all buffers and close vim with:

:xa

I really love finding stuff like that. While that solved the immediate need, as written, it would not be able to deal with file names that have spaces in them. Since that sort of thing bugs me, I set up some test files and gave it a try:

mike@sleepycat:~/projects/vimtest☺  tail ./*
==> ./fileone <==
blah
blah
cats
blah

==> ./filethree <==
blah
rabbits
blah

==> ./file two <==
blah
racoons
dogs and cats
blah

After a little tinkering I figured it out with a little help from the xargs man page. Its not something I would want to type often but this will make a very useful alias or script some time:

grep -Zril cats . | xargs -0 sh -c 'vim -O "$@" < /dev/tty' vim

Bash Boilerplate

I’ve ended up doing a lot of bash scripting lately and am really shocked at how difficult it is to sort out all most mundane things like handling long and short options and some other cases like ensuring the script is run as root. So here is my bash boilerplate; 45 lines of time and sanity saving bash script. It has been lovingly assembled in Franenstinian fashion from about a dozen blogs and stackoverflow answers and owes a great debt to missiondata’s excellent post on getopt. Thank you internet.

I have several scripts using variations on this now that I use reasonably regularly and its a real time saver to use this as my starting point. If you notice a mistake or something that is flat out a bad idea please let me know. I’d like to make this as solid as possible.


#!/usr/bin/env bash
# set the script to exit immediately on error
set -e

usage(){
cat <<'EOT'
Call this script with...
EOT
exit 0;
}

# exit if there are no arguments
[ $# -eq 0 ] && usage

set -- `getopt -n$0 -u -a --longoptions "help dogs: cats:" "hd:c:" "$@"`

# $# is the number of arguments
while [ $# -gt 0 ]
do
case "$1" in
-d|--dogs) dogs="$2"; shift;;
-c|--cats) cats="$2"; shift;;
-h| --help) usage;;
--) shift;break;;
*) break;;
esac
shift
done

cleanup_before_exit () {
# this code is run before exit
echo -e "Running cleanup code and exiting"
}
# trap catches the exit signal and runs the specified function
trap cleanup_before_exit EXIT

# if this script needs to be run as root
# we can check like this:
# if [ ! `id -u` -eq 0 ]; then
#  echo "You need to call this script using sudo."
#  exit 1
# fi

# OK now do stuff
echo "$cats and $dogs living together, mass hysteria!"