Reputation: 797
I want to write a simple bash script to wrap the default unix/linux find program in bash to find multiple files matched.
Here is my program named my_find_command
:
#!/bin/bash
patt=""
first=true
for i in "$@"; do
if [ "$first" = true ]; then
patt="-name '$i'"
first=false
else
patt="${patt} -o -name '$i'"
fi
done
echo "$patt"
find . -type f \( ${patt} \)
echo 'done'
Assume I do have some files that the find
command would be able to return some files.
But when I call my_find_command icon.png profile.png
I got nothing.
What went wrong here?.
Upvotes: 2
Views: 414
Reputation: 113864
Quotes within strings do not work the way you want them to. You are correct that ./my_find_command icon.png
will not find icon.png
. But, it will find 'icon.png'
. For example:
$ ls
'icon.png' my_find_command
$ ./my_find_command my_find_command icon.png
-name 'my_find_command' -o -name 'icon.png'
./'icon.png'
done
The problem comes from trying to put multiple command arguments in a variable. For a full explanation of the ways that this goes wrong, see "I'm trying to put a command in a variable, but the complex cases always fail!". Instead, use an array:
#!/bin/bash
patt=()
for i in "$@"; do
if [ "${#patt}" -eq 0 ]; then
patt=(-name "$i")
else
patt+=(-o -name "$i")
fi
done
echo "${patt[@]}"
find . -type f \( "${patt[@]}" \)
echo 'done'
This now prints the correct files:
$ ls
'icon.png' icon.png my_find_command
$ ./my_find_command my_find_command icon.png
-name my_find_command -o -name icon.png
./icon.png
./my_find_command
done
To demonstrate that wildcards work correctly:
$ ls
'icon.png' icon.png my_find_command
$ ./my_find_command my_find_command '*icon.png*'
-name my_find_command -o -name *icon.png*
./icon.png
./my_find_command
./'icon.png'
done
Upvotes: 3