Wednesday, April 29, 2015

Finding Files by Name That Contain/Don't Contain a String in a Bash Script

When trying to find things, sometimes I use the IDE, but most of the time I drop down to terminal.

Today I needed to find persistence.xml files that weren't in Maven target directories that required a classname.

Easy right? Without a script it's not bad.

To find files named persistence.xml containing ".MyClassName" and where target is not in the path:

find . -name 'persistence.xml' -exec grep -H -il '.MyClassName' {} \; | grep -v target

and to find files named persistence.xml not containing ".MyClassName" and where target is not in the path:

find . -name 'persistence.xml' -exec grep -H -iL '.MyClassName' {} \; | grep -v target

However, I thought I'd create a script to make this easier in the future.

It gets a little tricky to use arguments passed into a bash script along with find -exec grep, especially if you need to escape anything like a dot/period in the grep.

The idea is that you need to use "sh -c" since find exec uses exec and not a shell, and you want variable expansion to use the variable you passed in (e.g. $1), but then you have to pass in the variable and the argument passed from find to exec, which is the pathname of the found file.

Here's an example solution:

#!/bin/bash
while test $# -ne 1; do
  echo "Usage: findinpersistencexml MyClassName"
  echo
  echo "Finds the persistence.xml files that do and do not contain the specified unqualified classname."
  test "$1" = "-h" || test "$1" = "--help" && exit 0 || exit 1
done

echo "persistence.xml with ${1}:"
find . -name 'persistence.xml' \
  -exec sh -c \
  "grep -H -il \\\\.$1 {}" "{}" "$1" \; \
  | grep -v target
echo
echo "persistence.xml without ${1}:"
find . -name 'persistence.xml' \
  -exec sh -c \
  "grep -H -iL \\\\.$1 {}" "{}" "$1" \; \
  | grep -v target
If you wanted to also look for </class at the end and use single quotes around that:

#!/bin/bash
while test $# -ne 1; do
  echo "Usage: findinpersistencexml MyClassName"
  echo
  echo "Finds the persistence.xml files that do and do not contain the specified unqualified classname."
  test "$1" = "-h" || test "$1" = "--help" && exit 0 || exit 1
done

echo "persistence.xml with ${1}:"
find . -name 'persistence.xml' \
  -exec sh -c \
  "grep -H -il '.$1</class' {}" "{}" "$1" \; \
  | grep -v target
echo
echo "persistence.xml without ${1}:"
find . -name 'persistence.xml' \
  -exec sh -c \
  "grep -H -iL '.$1</class' {}" "{}" "$1" \; \
  | grep -v target

No comments: