我希望能够运行一个查找,该查找使用用户输入值($ 1 $ 2 $ 3 .. $ 9或$#的值)的所有可能变化来查看文件是否存在。但是一旦用户只输入3个参数(搜索模式),find命令开始变得有点笨拙:
docs=($(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*" ))
有没有办法告诉find获取指定的多个模式并搜索每个可能的顺序变量以查看文件是否存在?对于大多数情况,我想用户只会输入2-4个输入参数,但我想允许使用最多9个输入变量进行搜索,而我讨厌想象$#= 9时的find命令。< / p>
答案 0 :(得分:2)
我喜欢你的问题。您需要生成位置参数的所有排列。很有趣:
#!/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[@]}"
函数perm
以有趣符号(空格,换行符等)100%安全的方式生成给定参数的所有排列。它是一个简单的递归函数,所以如果用太多的参数提供它可能会很快爆炸,但是,嘿,你不想生成一个包含40个元素的集合的所有排列,对吗?
现在这当然是一个非常糟糕的方法!你当然不想这样做。
而不是
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*"
为什么不呢?
find /dir1 /dir2 -type f -iname "*$1*" -iname "*$2*" -iname "*$3*"
(-iname
&#39;之间隐含和。
如果您需要一个脚本来构建搜索命令:
#!/bin/bash
searchargs=()
for i; do
searchargs+=( -iname "*$i*" )
done
find /dir1 /dir2 -type f "${searchargs[@]}"
好多了,嗯?
当然,如果你有重复的论点,这并不完全等同于以前的排列mumbo。但嘿,谁在乎,真的吗?代码简单性在这里获胜。
哦,最后一句话,做:
docs=( $(find ...) )
非常糟糕(想想带有空格的文件名)。