我希望能够运行一个查找,使用用户输入值的所有可能的顺序变化($1 $2 $3 .. $9 或 $# 的值)来查看文件是否存在。但是,一旦用户仅输入 3 个参数(搜索模式),查找命令就开始变得有点笨拙:
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 命令可能是什么样子。
最佳答案
我喜欢你的问题。您需要生成位置参数的所有排列。充满乐趣:
#!/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
之间有一个隐式的和)。
如果您需要脚本来构建搜索命令:
#!/bin/bash
searchargs=()
for i; do
searchargs+=( -iname "*$i*" )
done
find /dir1 /dir2 -type f "${searchargs[@]}"
好多了,嗯?
当然,如果您有重复的参数,这并不严格等同于之前的排列组合。但是,嘿,谁在乎呢,真的吗?代码简单性在这里获胜。
哦,最后一句话,做:
docs=( $(find ...) )
非常糟糕(想想带空格的文件名)。
关于bash - 可以找到搜索指定输入变量的多个顺序变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23396875/