5

我正在尝试在 Bash 中编写一个未找到的句柄,它执行以下操作:

  1. 如果 $1 存在并且它是一个目录,cd则进入它。
  2. 如果 $1 存在于用户定义的目录$DEV_DIR中,则 `cd 进入它。
  3. 如果前面的条件不适用,则失败。

现在我有这样的事情:

export DEV_DIR=/Users/federico/programacion/

function command_not_found_handle () {
    if [ -d $1 ]; then          # the dir exists in '.'
        cd $1
    else
        to=$DEV_DIR$1
        if [ -d $to ]; then
            cd $to
            echo `pwd`
        else
            echo "${1}: command not found"
        fi
    fi
}

虽然它似乎在工作(echo pwd命令打印预期的目录),但实际 shell 中的目录并没有改变。

我的印象是,由于这是我.bashrc的 shell 内部的一个函数,所以我可以做到这一点,cd但显然这不起作用。任何有关如何解决此问题的提示将不胜感激。

4

4 回答 4

3

认为发生的事情是 shellfork()在设置任何重定向之后但在查找命令之前,因此command_not_found_handle不会影响交互式 shell 进程。

于 2011-03-20T17:49:51.650 回答
1

您似乎想要做的事情可能部分可能使用该autocd功能:

shopt -s autocd

来自man bash

autocd - 如果设置,作为目录名称的命令名称将被执行,就好像它是 cd 命令的参数一样。此选项仅由交互式 shell 使用。

否则,只需创建一个按名称调用的函数,该函数执行您尝试使用command_not_found_handle的操作。

于 2011-03-20T21:39:22.413 回答
0

如果您将此程序作为脚本在主 shell 中运行,它不会更改方向,因为它在执行时会创建一个子 shell。如果您在当前 shell 中获取脚本,那么它将具有预期的效果。

~/wbailey> source command_not_found.sh

也就是说,我认为以下将达到相同的结果:

wesbailey@feynman:~/code_katas> cd xxx 2> /dev/null || cd ..; pwd
/Users/wesbailey

只需将“..”替换为您的 env var 定义的目录并在您的 .bashrc 文件中创建一个别名。

于 2011-03-20T17:55:27.760 回答
0

我有同样的愿望,我使用了一段时间的解决方案是通过gnome-terminal --tab --working-directory="$FOLDER"command_not_found句柄内部发出命令在 gnome 终端中打开一个新选项卡。

但是今天我提出了一个解决方案,它不依赖于特定的终端应用程序,但具有完全预期的行为。

该解决方案使用PROMPT_COMMAND, 在每个提示之前运行。绑定到一个函数,该PROMPT_COMMAND函数负责检查与当前 shell 相关的文件,并 cd'ing 进入该文件中指定的目录。

然后,command_not_found_handle当需要更改目录时填充文件。command_not_found_handle如果当前目录是 git 存储库并且名称与现有分支匹配,我的原始版本也会签出 git 分支。但是为了继续专注于回答当前的问题,我已经剥离了那部分代码。

command_not_found_handle用于搜索与给定名称匹配的find目录,并且从配置的列表开始,在目录树中仅深入 2 级。

要添加的代码bash_rc如下:

PROMPT_COMMAND=current_shell_cd
CD_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/bash-cd/$$.cd"

current_shell_cd() {
    if [ -r "$CD_FILE" ]; then
        local CD_TARGET="$( cat "$CD_FILE" )"
        [ ! -z "$CD_TARGET" ] && cd "$CD_TARGET" 2>/dev/null
        rm "$CD_FILE"
    fi
}

command_not_found_handle () { 
    local COMMAND="$1";
    # List folders which are going to be checked
    local BASE_FOLDER_LIST=(
        "$HOME/Desenvolvimento"
        "/var/www/html"  
        "$HOME/.local/opt/"
    )
    local FOLDER=$(
        find "${BASE_FOLDER_LIST[@]}" \
             -maxdepth 2 -type d \
             -iname "$COMMAND" -print -quit )
    if [ ! -z "$FOLDER" -a -d "$FOLDER" ]
    then
        mkdir -p "$( dirname "$CD_FILE" )"
        echo "$FOLDER" > "$CD_FILE"
    else
        printf "%s: command not found\n" "$1" 1>&2
        return 127
    fi
}
于 2020-10-09T18:27:49.857 回答