我注意到bash中bash补全的一个非常酷的功能。假设我有一个包含文件的目录
a.java
a.class
b.java
b.class
如果我开始输入vim a
Tab ,bash将自动完成a.java
。它知道我不想编辑a.class
我想知道它如何实现这种行为。在我的bash_completion.d
目录中,有一堆completion
文件,但是vim
没有一个文件。
vim
如何实现此行为,以及如何修改它以使其包含其他要忽略的文件扩展名?
答案 0 :(得分:8)
在Ubuntu上,如果我安装软件包bash-completion
,则可以通过以下方式查看其内容:
$ dpkg -L bash-completion
在输出中,列出了/etc/bash_completion
。
在内部,编写了以下命令:
. /usr/share/bash-completion/bash_completion
它将获取文件/usr/share/bash-completion/bash_completion
。
这些文件vary从一个操作系统到另一个操作系统的位置:
注意:我使用的是Mac,在macOS上,bash补全文件(默认情况下)存储在
/usr/local/etc/bash_completion
中,而bash_completion.d
目录位于/usr/local/etc/bash_completion.d
在我的系统上,/usr/share/bash-completion/bash_completion
包含以下行:
_install_xspec '*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
我认为这一行是您所观察到的行为的原因。
如果要调整它以使bash在foo
命令后完成文件名时排除bar
和$ vim
扩展名,则可以尝试following procedure。 / p>
~/.bash_completion
在后者内,写:
for bcfile in ~/.bash_completion.d/* ; do
[ -f "$bcfile" ] && . $bcfile
done
创建~/.bash_completion.d/
目录。
在此目录中,创建一个vim
文件。
在后者内,写:
complete -f -X '*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class|foo|bar)' vi vim gvim rvim view rview rgvim rgview gview
complete
是bash内置命令,可让您指定应如何完成命令名称的参数。
-f
是-A file
的简写,它指定bash表示您只希望在建议中看到文件名。
-X
排除与以下模式匹配的任何内容。
请注意,我只是复制了/usr/share/bash-completion/bash_completion
中使用的模式,并添加了foo
和bar
扩展名:
*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class|foo|bar)
^^^^^^^
由您决定修改模式以排除要避免的真实扩展名。
该模式之后的名称告诉bash它应该针对哪些命令排除这些扩展名。
在上一个命令中,它们是:
vi vim gvim rvim view rview rgvim rgview gview
它们都调用Vi或Vim的版本。您可以在末尾添加其他编辑器名称。
有关更多信息,请参见:
$ man bash
查找READLINE
部分和Programmable Completion
子部分,以及complete
部分中内置的SHELL BUILTIN COMMANDS
的描述。
另请参阅An introduction to bash completion part 1和An introduction to bash completion part 2。