bash - 可以找到搜索指定输入变量的多个顺序变体

标签 bash find

我希望能够运行一个查找,使用用户输入值的所有可能的顺序变化($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/

相关文章:

linux - find 命令重命名每个文件和目录。最大深度 1

linux - 如何撤消删除我的 .git/文件夹?

bash - 在等待多个 bash 进程完成时,我应该使用 ${pods[*]} 还是 ${pods[@]} ?

bash - 让 ssh 在目标机器上后台执行命令

linux - 有没有办法在特定时间在linux中找到修改过的文件

arrays - 使用枚举查找数组(Swift 5)中的所有组合

linux - 如何让 Perl 遍历目录中的所有文件?

linux - 如何在 Bash 中创建一个 3 秒计时器?

jquery - 使用 JQuery 查找并替换子元素

vb.net - 如何从 VB.NET 的列表中找到对象的索引?