Your function disables filename globbing, but you call it with a glob that the shell expands (filename globbing is not turned off in the shell that you call it from).
In other words, the glob in your command
find -name *c
is expanded before your find
function is called. This results in a call to find
inside the function that the utility can't understand.
You could solve that by calling your function with a quoted argument:
find -name "*c"
but notice how now the function is totally useless as it just replicates the command that you've already typed in.
In addition to being useless, it's also wrong. Since $@
is unquoted in your code, it will split the arguments on whitespaces (by default). This means that you can't use e.g.
find -name "* *"
to find names with spaces in them.
Also note that due to the eval
, the shell would perform expansions on the contents of $@
. This means that
find -name '$(echo hello)'
would not find files called $(echo hello)
but hello
.
Another thing is that if the calling shell already uses set -f
, then this will be disabled by the function.
Let's create a useful function instead. A function that looks for a number of filename patterns, for example:
myfind "*.c" "*.txt" "* *"
We'd like the above command to return the pathnames that end with .c
or .txt
or that contain spaces.
Here's the function:
myfind () {
# Replace each positional parameter "$pattern"
# with -o -name "$pattern"
for pattern do
set -- "$@" -o -name "$pattern"
shift
done
shift # shift off the initial "-o"
find . "$@"
}
Given the above call of the function, it will end up executing
find . -name '*.c' -o -name '*.txt' -o -name '* *'
If you are more comfortable using bash
arrays for lists, and don't mind a bit more typing:
myfind () {
local -a args
# Build the argument list for find by adding
# -o -name "$pattern"
# for each positional parameter
for pattern do
args+=( -o -name "$pattern" )
done
args=( "${args[@]:1}" ) # remove the initial "-o"
find . "${args[@]}"
}
eval
, and use"$(command -v find)" "$@"
– cuonglm Feb 12 '19 at 02:08Ctrl+C
– builder-7000 Feb 12 '19 at 02:15command -v find
still report yourfind
function, maybe better to rename the function to something else other thanfind
. In any case, I don't think it's a good solution, because*.c
still be evaluated before passing to your function, so it won't work. – cuonglm Feb 12 '19 at 02:23