如果我开始输入命令或文件名,我可以使用 Tab 键自动完成我的字符串。有没有办法改变当前 bash 会话的自动完成行为?
例如
Tab Tab在当前会话中按下时,*.txt
只会显示包含的文件。
自动完成功能如何工作?是否有一组环境变量或可以调整的东西来改变自动完成行为?
答案1
在该bash_completion
机制中,bash 函数_filedir_xspec()
负责文件名和目录名的补全。这个函数可以在脚本中找到/etc/bash_completion
。
您可以编辑该函数并添加包含正则表达式的行。例如使用这个函数(它是原始函数的副本):
_filedir_xspec()
{
local IFS cur xspec
IFS=$'\n'
COMPREPLY=()
_get_comp_words_by_ref cur
_expand || return 0
# get first exclusion compspec that matches this command
xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
"$BASH_COMPLETION" )
# prune to leave nothing but the -X spec
xspec=${xspec#*-X }
xspec=${xspec%% *}
local -a toks
local tmp
toks=( ${toks[@]-} $(
compgen -d -- "$(quote_readline "$cur")" | {
while read -r tmp; do
# see long TODO comment in _filedir() --David
printf '%s\n' $tmp
done
}
))
# Munge xspec to contain uppercase version too
eval xspec="${xspec}"
eval xspec="!*.txt" #<---- HERE add your regex, that's the only line changed
local matchop=!
if [[ $xspec == !* ]]; then
xspec=${xspec#!}
matchop=@
fi
[[ ${BASH_VERSINFO[0]} -ge 4 ]] && \
xspec="$matchop($xspec|${xspec^^})" || \
xspec="$matchop($xspec|$(printf %s $xspec | tr '[:lower:]' '[:upper:]'))"
toks=( ${toks[@]-} $(
eval compgen -f -X "!$xspec" -- "\$(quote_readline "\$cur")" | {
while read -r tmp; do
[ -n $tmp ] && printf '%s\n' $tmp
done
}
))
[ ${#toks[@]} -ne 0 ] && _compopt_o_filenames
COMPREPLY=( "${toks[@]}" )
}
请注意新部分32号线:
eval xspec="!*.txt"
该语句稍后用于compgen
删除所有与正则表达式不匹配的条目。我不建议编辑该文件/etc/bash_completion
。相反,使用上面的内容和source
文件(如果需要)创建一个新文件:
source /path/to/file
现在,shell 中由函数完成的所有命令/应用程序 _filedir_xspec()
现在仅使用文件名完成*.txt
。
答案2
您也可以仅将其用于某些程序或您的自定义脚本或命令。
要仅显示txt
建议中具有扩展名的文件,只需编写一个 shell 脚本并source
在当前会话中:
# Autocomplete file /path/to/file/sample-completion.sh
# for the command `sample`
_sample(){
COMPREPLY=($(compgen -f -X "!.*[.][tT][xX][tT]$" -- "$2"))
}
complete -F _sample sample
并通过调用获取它:
$ source /path/to/file/sample-completion.sh
在此代码中,$2
当前单词正在完成。该-- "$2"
零件使compgen
仅过滤掉包含当前正在完成的单词的建议并将其放入COMPREPLY
。另外,该-f
选项告诉compgen
仅查找当前目录中的文件。最后但并非最不重要的-X
选项是过滤模式(看这里)排除匹配文件名。位于!
模式的开头否定这种行为。结果,仅.txt
显示具有扩展名的文件。$
正则表达式末尾的符号查找以给定模式结尾的匹配项。这[.]
意味着它将查找文字点,而不仅仅是任何字符 - 这是正则表达式中点的默认含义。该[tT][xX][tT]
部分表示模式将匹配所有这些情况:“txt, txT, tXt, tXT, Txt, TxT, TXT, TXt”。
答案3
倚在接受的答案来自@chaos,我建议这个功能修补需要时现有的完成功能:
patchFDxspec(){
. <(type _filedir_xspec | sed -e '1d;s/\(eval xspec="\).*$/&\n\1!*.txt";/');
}
执行此函数将为_filedir_xspec
当前会话打补丁。
如果您需要除 之外的其他扩展名.txt
,您可以修改该函数以将所需的后缀设为$1
.