I can run the following command in bash without any errors:
$ find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
I wrote a function in .bash_aliases to quickly run this command:
search() {
local file_type file_types find_cmd opt OPTARG OPTIND or pattern usage
usage="Usage: search [OPTION] ... PATTERN [FILE] ...
Search for PATTERN in each FILE.
Example: search -t c -t h 'hello world' /code/internal/dev/ /code/public/dev/
Output control:
-t limit results to files of type"
if [[ $1 == --help ]]; then
echo "$usage"
return
fi
file_types=()
while getopts ":t:" opt; do
case $opt in
t)
file_types+=("$OPTARG")
;;
?)
echo "$usage"
return
;;
esac
done
shift $((OPTIND-1))
if (( $# == 0 )); then
echo "$usage"
return
fi
pattern=$1
shift
if (( $# == 0 )); then
echo "$usage"
return
fi
find_cmd=(find "$@" '\(')
or=""
for file_type in "${file_types[@]}"; do
find_cmd+=($or -name \'*.$file_type\')
or="-o"
done
find_cmd+=('\)' -exec grep -IH "$pattern" {} '\;')
"${find_cmd[@]}"
}
However, the function throws an error:
find: paths must precede expression
If I change the last line to echo "${find_cmd[@]}"
, it prints the exact same command as above:
$ search -t cs -t cshtml UserProfileModel /d/Code/Web/Development/Source/
find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
I don't understand why it would work when run in the console but fail when run inside a function.
Also, if I simplify the function to just the command it works:
search() {
find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
}
I am editing .bash_aliases in Notepad++, but I have made sure the line endings are Unix format.
Edit
Per F. Hauri's advice below, I enabled debugging. Apparently this is the command that's actually being executed:
find /d/Code/Web/Development/Source/ '\(' -name ''\''*.cs'\''' -o -name ''\''*.cshtml'\''' '\)' -exec grep -IH UserProfileModel '{}' '\;'
I'm not sure what to make of this information. Removing the escape character before the parens cause it to throw a different error:
find: missing argument to -exec
-name
patterns e.g.-name '*.cs'
and similar arguments when you runfind
. Otherwise the shell may expand the glob to a list of matching files from the current directory. Quoting ensures that*.cs
is passed unexpanded tofind
.