bash_completion
我正在尝试为我的脚本创建规则rmpxe
。该脚本将<hostname>
其作为唯一的参数。然后,它将该主机名解析为<ip_address>
并删除相应的符号链接/srv/tftp/pxelinux.cfg/<ip_address>
。
<ip_address>
符号链接中的IP 地址/srv/tftp/pxelinux.cfg/<ip_address>
是十六进制格式,但我用 C ( getnameinfo
) 编写了一个简单的程序,它将这个十六进制 IP 地址解析为主机名。
因此,我可以使用我的程序getnameinfo
从十六进制 IP 获取主机名:
$ getnameinfo 0A6F010B
server1.mydomain.com
例如,以下命令将删除符号链接/srv/tftp/pxelinux.cfg/0A6F010B
$ rmpxe server1.mydomain.com
现在我的bash_completion
问题是:我创建了以下代码,该代码工作正常,只是它没有完成主机名(如我的脚本所期望的),而是完成了十六进制 IP 地址(即我的目录中的符号链接文件/srv/tftp/pxelinux.cfg/
)。我需要以某种方式集成到此代码中,在参数自动完成之前,它将首先解析为主机名。
_rmpxe()
{
local word
COMPREPLY=()
if [ 1 -eq "$COMP_CWORD" ]; then
pushd /srv/tftp/pxelinux.cfg &>/dev/null || return 1
word="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=($(compgen -f "$word"))
popd &>/dev/null
fi
}
complete -F _rmpxe rmpxe
换句话说,目前我的 bash 完成工作如下:
$ ls /srv/tftp/pxelinux.cfg
0A6F010B 0A6F010C 0A6F010D 0A6F010E
$ rmpxe <tab>
0A6F010B 0A6F010C 0A6F010D 0A6F010E
然而,我需要它像这样工作:
$ rmpxe <tab>
server1.mydomain.com server2.mydomain.com server3.mydomain.com
答案1
因为您使用了compgen -f
,含义compgen
将列出当前路径下的所有文件和目录。在你的情况下,这意味着0A6F010B 0A6F010C 0A6F010D 0A6F010E
.
要获取主机名,您可以循环遍历当前路径,将每个 IP 提供给以getnameinfo
获取与该 IP 对应的主机名,将其保存到数组中,然后将此数组用作带有compgen -W
.
我在我的环境中做了一个简单的测试。我创建了一个文件/etc/bash_completion.d/cuonglm
:
_rmpxe() {
local word
COMPREPLY=()
if [ 1 -eq "$COMP_CWORD" ]; then
pushd /home/cuonglm/test &>/dev/null || return 1
word="${COMP_WORDS[COMP_CWORD]}"
HOST_ARR=()
for i in *; do
HOST_ARR+=($(/home/cuonglm/getnameinfo "$i"))
done
COMPREPLY=($(compgen -W "$(printf "%s " "${HOST_ARR[@]}")" -- "$word"))
popd &>/dev/null
fi
}
complete -F _rmpxe cuonglm
我使用了你的完整功能并做了一些修改:
- 我使用数组
HOST_ARR
来保存主机名。 - 循环当前目录(
pushd
之前感谢),将每个文件名输入getnameinfo
程序。 - 然后我用
compgen -W
compgen 创建一个单词列表来完成。
这是结果:
$ cuonglm <Tab>
$ cuonglm server<Tab>
server1.example.com server2.example.com
因为两个主机名具有相同的部分server
,所以 bash 将首先自动完成这部分。如果有其他主机名Server.example
:
$ cuonglm <Tab>
Server.example server1.example.com server2.example.com