使用变量隐藏的根前缀完成Tcsh和/或bash目录

7 bash tcsh tab-completion bash-completion

我试图在tcsh和/或bash中设置目录完成(两者都在我的网站上使用)稍微扭曲:对于特定命令"foo",我想完成使用自定义函数来匹配first/-deimited term到实际子树节点,然后按照正常目录完成任何连续的术语.它是cdpath和completion的组合,或者我想一种目录完成形式,其中起点由完成脚本控制.它的工作原理如下:

$ foo xxx<TAB>
(custom completion function produces choices it finds at arbitrary levels in the dir tree)
xxxYYY xxxZZZ xxxBLAH ...
foo xxxYYY/<TAB>
(normal directory completion proceeds from this point on, to produce something like:)
foo scene/shot/element/workspace/user/...
Run Code Online (Sandbox Code Playgroud)

我们想这样做是因为我们有一个大型的生产开发树(这是一个CGI生产设施),精通外壳的用户一直在导航和跳跃.抱怨是树的上层是繁琐和多余的; 他们只需要在第一个学期快速搜索,找到可能的"头部"选择并从那里完成目录.似乎可编程完成可以提供一种方法来实现这一点,但它变得相当难以捉摸.

我做了几次自定义bash和tcsh完成的尝试,但是我得到的最接近的是一种"单词完成"形式,用户必须将目录级别视为带空格的单独单词(例如foo scene/shot)/element/workspace/...).我可以继续攻击我目前的脚本 - 但我一直想知道是否有一些我不理解的东西 - 这是我第一次尝试完成程序,而且这些文档和示例在shell书籍和互联网上相当薄弱.如果有任何完成大师可以让我走上正轨,我会很感激.

FWIW:这是我到目前为止所得到的(首先是tcsh,然后是bash).请注意,静态根"/ root/sub1/sub2/sub3"只是搜索功能的占位符,可以在不同级别找到不同的匹配项.如果我可以让它工作,我可以稍后进入搜索功能.同样,两个示例都执行单词完成,这需要用户在每个匹配的术语后键入一个空格(我还必须删除函数中的空格以构造实际路径,哎呀!)

TCSH示例(注意该函数实际上是一个bash脚本):

complete complete_p2 'C@*@`./complete.p2.list.bash $:1 $:2 $:3 $:4 $:5 $:6 $:7 $:8 $:9`@@'

#!/bin/bash --norc

# complete.p2.list.bash - Completion prototype "p2" for shotc command

# Remove spaces from input arguments
ppath=`echo $@ | sed -e 's/ //g'`

# Print basenames (with trailing slashes) of matching dirs for completion
ls -1 -d /root/sub1/sub2/sub3/$ppath* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}'
Run Code Online (Sandbox Code Playgroud)

基础示例:

_foo() 
{
    local cur prev opts flist
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Get all command words so far (omit command [0] element itself), remove spaces
    terms=`echo ${COMP_WORDS[@]:1} | sed -e 's/ //g'`

    # Get basenames (with trailing slashes) of matching dirs for completion
    flist=`ls -1 -d /root/sub1/sub2/sub3/${terms}* 2>/dev/null | sed -e 's#^.*/##' | awk '{print $1 "/"}' | xargs echo`

    COMPREPLY=( $(compgen -W "${flist}" ${cur}) )
    return 0
}
complete -F _foo foo
Run Code Online (Sandbox Code Playgroud)

ire*_*ses 0

您可以只创建一个指向树中第一个有趣节点的符号链接。过去,当我懒得自动完成大型目录树时,我就这样做过。