I've got a script that uses find
to look for files that match user input. Basically, the user enters something like test*
and it's supposed to find all matching files.
The problem I'm having is that if there is a file in the current directory that matches the filename pattern the user entered, it only looks for that file. That is, if the user enters fred*
and there is a file in the current directory called frederica
, the script only ever finds files named frederica. Here's an example of the problem:
>ls
test1 test2 test3 test4 test5 words
>tmp()
> {
> my_file="$1"
> find . -iname "$my_file"
> }
>tmp test*
./test1
>
If I enter tmp test*
, I would expect it to return the five files test1 through test5. Instead it only returns the first one. Further, if I searched on, say, /
, it would still only ever return files named test1 from every directory.
The actual script is more complex, of course, and I've developed a workaround involving a "wildcard option" (e.g., -w 1
means leading and trailing asterisks, etc.) but I'd really just like to be able to let the user enter a filename with a wildcard.
Thanks in advance
When you call your function the way you do, the shell that is interpreting the call tries to find matching files (this is done before entering the function), and different things can happen :
If the glob fails and the failglob
shell option is set, then the function will not be executed at all. You have probably not seen this because of default shell options.
Else if the glob fails and the nullglob
shell option is set, then the result of the glob is nothing at all, and no argument will be passed to your function. You have probably not experienced that either.
Else if the glob fails and the failglob
shell option is unset, then result of the glob is whatever the glob expression was, and this is used as the argument value. Then, this glob expression is passed as is to find
, and find
does what you want because it implements globbing internally. You are lucky that it works, but it works.
The glob succeeds and results in a list of files that is used as a list of arguments for your function. Your call find
using $1
, so only the first of these arguments is taken into account, resulting in the result you do not want.
Double quoting or single quoting disable globbing. If using from a script, you can therefore do:
tmp "test*"
If you want to use this command from the command line, your only option would be to entirely disable globbing, with set -f
, which might very well have drawbacks.