找到最接近的匹配文件夹

找到最接近的匹配文件夹

按“/”的出现次数对结果进行排序$ find . -name scripts -type d然后选择第一个结果的最佳方法是什么?

我想创建一个函数,该函数将cd指向项目中的公共文件夹。我希望它能够根据您的相对目录进行灵活调整。

因此,如果我有 10 个项目都具有相似的文件夹结构:

~/project-a/project/folder/structure
~/project-b/project/folder/structure
~/project-c/project/folder/structure

我可以:

$ cd ~/project-a
$ cdd structure

并被放入 ~/project-a/project/folder/struct

更新

我无法以任何可预测的方式对结果进行排序,例如:

$ find . -type d -name "themes"

./wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes
./wp-content/plugins/jetpack/modules/infinite-scroll/themes
./wp-content/plugins/smart-youtube/themes
./wp-content/plugins/wptouch-pro/themes
./wp-content/themes
./wp-includes/js/tinymce/themes

我希望该cdd函数能够下降到最接近的结果。在这个例子中,它是./wp-content/themes.

答案1

有了zsh,你可以这样做:

cdd() cd -- **/$1(/Od[1])

cdd themes

cdd函数查找所有类型的文件目录( /) 与作为参数 ( ) 给出的名称$1O按 epth 对它们进行排序d并选择第一个 ( [1])。

D它效率不高的地方是,即使当前目录中有匹配的目录,它也会爬行整个目录树(跳过隐藏目录,添加glob 限定符来更改它)。

要一次遍历目录树一层深度,您可以这样做:

cdd() {
  local dirs matches
  dirs=(.)
  while (($#dirs)) {
    matches=($^dirs/$1(N/[1]))
    if (($#matches)) {
      cd $matches[1]
      return
    }
    dirs=($^dirs/*(/N))
  }
  print >&2 Not found
  return 1
}

答案2

您不能使用 and 别名来解决此问题,因为别名不能在中间接受参数,只能在末尾接受参数。你需要一个函数来实现这一点。

以下函数可以满足您的要求:

cdd() { 
   cd `find . -type d -name "$1"|head -n1`
}

您必须将这些行添加到您的 .profile (或 .bashrc 文件)中,以便在您登录时执行(一次)。

为了进行测试,您可以将其放入一个文件中,例如名为func.sh,然后获取它(即使用“.”运算符执行它),以便它成为您环境的一部分:

. ./func.sh

注意:如果您对文件进行更改,func.sh则必须重新获取它。

然后您可以将其用作:

cdd <dirname>

该函数现在将<dirname>在当前路径及以下路径中搜索具有该名称的目录,并搜索cd到它找到的第一个匹配项 ( head -n1)。

您可以微调find操作,使其首先达到您想要的结果。看man find

要找到最接近的匹配,您可以对 find 的输出进行排序以给出最短的行:

find . -type d -name "$1"| awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- | head -n1

(该awk命令被盗自这里.)

这将返回 find 输出中最短的行。然而,如果您正在寻找目录proj并且您有这样的结构,它将返回错误的目录:

./d1/d2/d3/proj
./longdirname/proj

或者,您可以计算结果中的字符数/来解决这个问题。

答案3

find这个 bash 函数对当前目录下的所有目录层进行暴力破解,寻找指定的目录。

cdd() {
  if [ "$#" -ne 1 ]
  then
    printf '%s: Error: one directory name expected\n' "${FUNCNAME[0]}" >&2
    return
  fi

  maxdepth=$(find . -type d -exec sh -c 'printf %s "$1" | LC_ALL=C tr -dc / | wc -c' findshell {} \; | sort -n | tail -1)
  for((i=1; i <= maxdepth; i++))
  do
    dir=$(find . -mindepth "$i" -maxdepth "$i" -type d -name "$1")
    if [ -n "$dir" ]
    then
        command cd -- "$dir"
        return
    fi
  done
  printf '%s: %s: no such directory found\n' "${FUNCNAME[0]}" "$1" >&2
}

第一个find命令为当前目录下的每个目录执行一个 shell 片段; shell 片段将目录名称打印到tr&wc管道,该管道删除不是正斜杠的每个字符,然后计算正斜杠的数量。我从 ilkkachu 和 Stéphane Chazelas 那里学到了这个技巧这里。输出所有目录深度后,我们sort | tail找到最大的数字。该数字是我们需要搜索的最大目录深度。

之后,就是一个循环find,依次限制在每个目录深度,从当前目录开始一直到最深的目录。如果找到匹配项,我们cd就会退出该函数。如果没有找到匹配项,我们就会退出循环并向 stderr 打印一条消息。

答案4

也许使用 bash 的递归通配符功能:

shopt -s globstar  # in ~/.bashrc, or just in cdd() {}
cd **/structure/

我认为**扩展的发生顺序或多或少与查找的顺序相同,因此存在大多数相同的问题。但它是如此简单和有用,以至于你可能会忽略这一点!

具有多个参数的bash拒绝的最新版本cd所以这仅在只有一场比赛时才有效。否则你会得到cd: too many arguments.

所以你需要一个 shell 函数。array=( **/"$1"/ )如果非空,也许会使用第一个元素,但如果您正在编写一个函数,您可能想要find -depth -type d | tail -1或某些东西来获取最后的结果(最浅的结果之一)。或者-maxdepth如果您的树可能很深,则逐步使用。

相关内容