There are a few issues in your code:
The *.tex
pattern will be expanded when calling the function DO
, if it matches any filenames in the current directory. You will have to quote the pattern as either '*.tex'
, "*.tex"
or \*.tex
when calling the function.
The ls
is not needed. You already have both find
and grep
that are able to report the pathnames of the found files.
-name "$@"
only works properly if "$@"
contains a single item. It would be better to use -name "$1"
. For a solution that allows for multiple patterns, see below.
The function may be written
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for pattern do
set -- "$@" '-o' '-name' "$pattern"
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
Calling this function like
DO '*.tex' '*.txt' '*.c'
will make it execute
find . -type f '(' -name '*.tex' -o -name '*.txt' -o -name '*.c' ')' -exec grep -qF TODO {} ';' -print
This would generate a list of pathnames of files with those filename suffixes, if the files contained the string TODO
.
To use grep
rather than find
to print the found pathnames, change the -exec ... -print
bit to -exec grep -lF 'TODO' {} +
. This will be more efficient, especially if you have a large number of filenames matching the given expression(s). In either case, you definitely do not need to use ls
.
To allow the user to use
DO tex txt c
your function could be changed into
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for suffix do
set -- "$@" '-o' '-name' "*.$suffix" # only this line (and the previous) changed
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
DO f1.tex f2.tex
, and the find command would see... -name f1.tx f2.tex ...
, which is invalid.