按“/”的出现次数对结果进行排序$ 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
函数查找所有类型的文件目录( /
) 与作为参数 ( ) 给出的名称$1
,O
按 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
如果您的树可能很深,则逐步使用。