别名“cd”,以便它将自动自动完成并尝试移动到目录

时间:2011-06-24 19:07:45

标签: shell unix scripting alias cd

我想知道是否有人能做到这一点。说我有这个文件夹结构:

Folder A
    Folder Apple
    Folder Orange

如果我目前在文件夹A中,我会喜欢它,这样如果我输入“cd Ap”并点击回车,它会自动将我放入“Apple”子文件夹中。基本上,它会尝试自动完成并根据部分输入打开文件夹。

如果我当前在文件夹A中,并输入“cd ap”并按Enter(小写“a”),我会收到错误,因为它无法自动完成实际的子文件夹名称。这可能吗?我在Korn工作。

3 个答案:

答案 0 :(得分:0)

我不太会回答你的问题,但我会接近。在我看来,点击Tab键不是你的障碍,它是大写。我知道这种感觉,就像选择camelCase和不方便的打字。

我只是用bash,我的apoligies做到了这一点。如果我记得,bash和ksh相当接近,所以我希望它对你有用。

set completion-ignore-case on在bash中启用不区分大小写的完成。当然,这可以用于您可能想要的任何启动脚本。

祝你好运,告诉我们它是否适用于ksh!

答案 1 :(得分:0)

这是一个ksh函数(未经测试)

cd () {
  typeset prefix=$1
  typeset destination=""
  for f in *; do
    [[ -d "$f" ]] || continue
    case "$f" in 
      "$prefix"*) destination="$f"; break ;;
    esac
  done
  if [[ -z "$destination" ]]; then
    print -u2 "error: can't find directory with prefix '$prefix'"
  else
    command cd "$destination"
  fi
}

使用ksh, Esc \ 相当于bash tab-completion。

答案 2 :(得分:0)

对于Bash,您可以将以下内容添加到~/.bashrc。默认情况下,它将执行不区分大小写的匹配。它有点长,但它应该处理你抛出的任何东西(除了尝试从符号链接目录中自动完成cd ../my_direc之外(有关详细信息,请参阅here)。

如果您使用此脚本并将其保留为不区分大小写,那么您也可以将bind 'set completion-ignore-case on'添加到~/.bashrc,以便TAB完成也不区分大小写。

cd() {
    # Attempts to autocomplete the directory name
    #
    # If it fails to find a match, it'll still execute the input, in case the argument was
    # something like "-".
    case_insens=1 # set to one if you want it to try case-insensitive matching

    # for exact matches, cd immediately
    if [ -d "$1" ]; then
        builtin cd "$1"
        return
    fi
    # deal with no arguments passed
    if [ $# -eq 0 ]; then
        builtin cd
        return
    fi

    # first loop for case-sensitive (since we prefer a case-sensitive match)
    # for more on this globbing, see: bit.ly/1CZ9qym
    for element in "$(dirname "$1")"/{*,.[!.]*,..?*}; do
        # skip if this result is not a directory
        [ -d "$element" ] || continue

        if [[ "$(basename "$element")" == "$(basename "$1")"* ]]; then
            # if there's no ambiguity, switch to that folder
            if [ $(find -L "$(dirname "$1")" -maxdepth 1 -name "$(basename "$1")*" -type d 2>/dev/null | wc -l) -gt 1 ]; then
                echo "'$1' matches multiple results:  "
                echo "$(find -L "$(dirname "$1")" -maxdepth 1 -name "$(basename "$1")*" -type d 2>/dev/null)" 
                # try to cd anyway
                builtin cd "$1" &> /dev/null 
                unset case_insens element
                return
            else
                builtin cd "$element"
                unset case_insens element
                return              
            fi
        fi
    done

    if [ $case_insens -eq 1 ]; then
        #case-insensitive argument
        ci_arg="${1,,}"
    else
        builtin cd "$1"
        unset case_insens element
        return
    fi

    #Case-insensitive loop
    for element in "$(dirname "$1")"/{*,.[!.]*,..?*}; do
        # skip if this result is not a directory
        [ -d "$element" ] || continue   

        ci_element_name="$(basename "${element,,}")"
        if [[ "$ci_element_name" == "$(basename "$ci_arg")"* ]]; then
            # if there's no ambiguity, switch to that folder
            if [ $(find -L "$(dirname "$element")" -maxdepth 1 -iname "${ci_element_name}*" -type d 2>/dev/null | wc -l) -gt 1 ]; then
                echo "'$ci_arg' matches multiple results:  "
                echo "$(find -L "$(dirname "$element")" -maxdepth 1 -iname "${ci_element_name}*" -type d 2>/dev/null)"
                # try to cd anyway
                builtin cd "$1" &> /dev/null
                unset ci_arg case_insens ci_element element
                return
            else
                builtin cd "$element"
                unset ci_arg case_insens ci_element element
                return
            fi
        fi
    done
    # we still haven't found a match, so pass the (faulty) argument to the cd command
    builtin cd "$1"
    unset ci_arg case_insens ci_element element
}

使用示例

cd ~
cd deskt