I love your question. You need to generate all permutations of the positional parameters. Lots of fun:
#!/bin/bash
perms() {
if (($#==1)); then
ary_perms=( "$1" )
return
fi
local i
local ary=()
for ((i=1;i<=$#;++i)); do
perms "${@:1:i-1}" "${@:i+1}"
ary+=( "${ary_perms[@]/#/${!i}$sep}" )
done
ary_perms=( "${ary[@]}" )
}
sep='*'
perms "$@"
searchargs=()
for s in "${ary_perms[@]}"; do
searchargs+=( -o -iname "*$s*" )
done
searchargs=( "${searchargs[@]:1}" )
find /dir1 /dir2 "${searchargs[@]}"
The function perm
generates all permutations of the given arguments, in a way 100% safe regarding funny symbols (spaces, newlines, etc.). It's a straightforward recursive function so it might explode quickly if you feed it with too many arguments, but hey, you don't want to generate all the permutations of a set with 40 elements, do you?
Now this is of course a very bad method! You certainly don't want to do this.
Instead of
find /dir1 /dir2 -type f -iname "*$1*$2*$3*" -o -iname "*$1*$3*$2*" -o -iname "*$2*$1*$3*" -o -iname "*$2*$3*$1*" -o -iname "*$3*$1*$2*" -o -iname "*$3*$2*$1*"
why not just this?
find /dir1 /dir2 -type f -iname "*$1*" -iname "*$2*" -iname "*$3*"
(there's an implicit and between the -iname
's).
If you need a script to build up the search command:
#!/bin/bash
searchargs=()
for i; do
searchargs+=( -iname "*$i*" )
done
find /dir1 /dir2 -type f "${searchargs[@]}"
much better, eh?
Of course this is not strictly equivalent to the previous mumbo with permutations, if you have repeated arguments. But hey, who cares, really? code simplicity wins here.
Oh, a final remark, doing:
docs=( $(find ...) )
is very bad (think of filenames with spaces).