通常,如果我在 bash(在 macOS 上)工作,我也在 (Mac)Vim 中工作,在两者之间切换。从 Vim 切换到终端后,我犯的一个常见错误是在命令前包含一个前导冒号。我将:cd /path/to/project/dir/
在 Vim 中,然后切换到终端并键入完全相同的内容,当然,我不应该在那里以冒号开头。
所以,我不知道什么时候 bash 命令应该以冒号开头,每次我这样做我都不是故意的。那么,如果它是命令中的第一个字符,有没有办法让 bash 完全忽略冒号,并将其解释:cd ...
为cd ...
?
cam*_*amh 10
bash(1)
command_not_found_handle()
如果已定义且未找到要执行的命令,则将调用该函数。如果您尚未使用此功能(例如使用 Ubuntu 上的 command-not-found 包),您可以使用它去除冒号并重试:
command_not_found_handle() {
if [[ "${1:0:1}" != : ]]; then
printf "%s: %s: command not found\n" "$0" "$1" >&2
return 127
else
"${1/#:}" "${@:2}"
fi
}
Run Code Online (Sandbox Code Playgroud)
将该函数放入您的.bashrc
. 然后,当未找到以冒号开头的命令时,它将去掉前面的冒号并重试。
编辑:我会进一步解释一下,因为这里有一些不常见的扩展。
首先,如评论中所述,command_not_found_handle
是 bash 4 功能。Bash 4 于 2009 年 2 月发布。command_not_found_handle
调用该函数的参数是未找到的命令和该命令的参数。即$1
未找到$2
命令,之后是未找到命令的参数。这在命令执行下描述在手册页中的进行了。
"${1:0:1}"
是一个扩展,它从$1
, 从长度为 1 的位置 0获取子字符串。也就是说,它从 中提取第一个字符$1
,其中$1
是未找到的命令。这在手册页的参数扩展下记录为${parameter:offset:length}
。
如果 的第一个字符$1
不是冒号,我们会打印一个错误并返回 127 的退出值。 127 是 bash 在没有找到要执行的命令时使用的退出代码,如COMMAND EXECUTION 中所述手册页中的所述。
"${1/#:}"
扩展为$1
去除任何领先的冒号。如果开头没有冒号,则它相当于一个普通的$1
,但由于我们所处条件的分支,我们知道它无论如何都以冒号开头。 此扩展记录在部分手册页中的参数扩展下${parameter/pattern/string}
.
"${@:2}"
从第二个开始扩展到位置参数。此扩展记录在本节手册页的参数扩展下${parameter:offset}
,作为数组和@
. 也就是说,它不是提取子字符串,而是扩展到数组的元素。
最终结果是,如果运行未找到的命令并且它有一个前导冒号,我们将去掉冒号以形成一个新命令并将原始参数传递给新命令。这将最终以递归方式工作,就好像没有找到第二次尝试运行命令一样,command_not_found_handle()
将再次执行。这意味着您可以运行:::mkdir
并且它最终仍会运行mkdir
。