zsh 完成:完成 /dev 中的块设备

zsh 完成:完成 /dev 中的块设备

对于我的脚本,我需要在 中完成块设备/dev,这样当我这样做时

my_script.sh <TAB>

它将完成并为我提供(不在子目录中)/dev/列出的所有磁盘。/dev例如:

my_script.sh <TAB>
my_script.sh /dev/

my_script.sh /dev/<TAB>
sda sdb sdc mmcblk0p1

my_script.sh /dev/sd
sda sdb sdc 

我应该如何修改我的完成度才能使其按描述工作?

_arguments -S : \
    '--foo' \
    '--bar' \
    '*:file:_files'

答案1

尝试:

_arguments -S : \
    '--foo' \
    '--bar' \
    '*:block devices:(( /dev/*(-%b:t) ))'

(-%b:t)是一个 glob 限定符,%b用于选择块设备,-以便在符号链接解析后进行选择,修饰符:t仅选择t这些文件的所有文件。

你可以使用_files, 和益处例如从着色:

_arguments -S : \
    '--foo' \
    '--bar' \
    '*:block devices:_files -W /dev -g "*(-%b)"'

我们使用-W的选项在此处_files指定W来查找这些文件,但仍然提供 的子目录,/dev以便您可以在其中找到更多块设备。

如果在 Linux 上,您可以使用

    '*:block devices:_files -W /sys/class/block'

或者:

    '*:block devices:(( /sys/class/block/*(:t) ))'

仅获取这些块设备的内核名称。

答案2

由于您只查找块设备,因此需要两个单独的步骤:

首先,您需要确定其中哪些特殊的准文件/dev实际上是块设备。这可以使用 来完成stat。该命令在 unix 中相当普遍,但如果由于某种原因您的发行版中没有它,您可以使用apt install coreutils.

以下命令创建一个由 /dev 内找到的块设备(以 800 开头的设备)全名组成的数组

blockdevs=($(stat -c "%t %n" /dev/* | grep "^8" | cut -d' ' -f2))

笔记:如果您正在寻找的不仅仅是实际的块设备(并非所有文件名/dev都是块设备。除了普通文件和目录之外,还会有“字符特殊文件”,例如各种子类型,例如/dev/tty/dev/zero,或符号链接,例如/dev/core)需要编辑上面的数组声明。


获得数组后,您可以根据其存储的值创建相应的补全(引号非常重要):

compctl -g "${blockdevs}" my_script.sh

现在,如果您的命令行以 开头my script.sh并点击TAB,完成器将自动填写/dev/' and then display the names of blockdevices found in the top-most level of that directory (i.e./dev/ 的起始前缀。`)。

这种使用数组值的方法适用于所有类型的自定义完成。基本上它所做的就是检查第一个单词是否匹配myscript.sh,然后如果没有检测到其他输入作为第二个参数,则它匹配并仅显示(:t)在中找到的文件名(使用修饰符)结果/dev

在终端中执行这两行代码,或者将它们都添加到 ~/.zshrc 以持久保存完成。

相关内容