Iva*_*lez 8 bash autocomplete shell-script shell-builtin
我编写了一个名为 的脚本prpsls,它在目录中创建或编辑文件~/proposals。
现在我正在为其编写自动完成脚本,并且尝试以这样的方式进行设置:在点击Tab后,complete内置列表会列出目录中的文件和目录~/proposals,而不管当前工作目录如何。
我想要实现的行为与我所做的完全一样complete -f prpsls,但我希望它始终完成目录的内容,而不是列出当前目录中的文件和目录~/proposals。
例如,当我写lsand tab时,它显示:
$ pwd
/home/user/base_directory
$ ls
file_01 file_02 subdir_01/
Run Code Online (Sandbox Code Playgroud)
如果我写subdand Tab,它会自动完成为subdir_01. 如果我再次按 Tab 键,它会显示以下内容dir_01:
$ ls subdir_01/
file_03 subdir_02/
Run Code Online (Sandbox Code Playgroud)
我正在寻找的行为是类似的:
$ pwd
/home/user/any/directory/it/should/not/matter
$ prpsls # Tab here
proposal_01 proposal_02 job_01/
$ prpsls job_01/ # Tab again
proposal_03 proposal_draft
Run Code Online (Sandbox Code Playgroud)
complete我的问题是:是否可以通过内置实现此行为?如果没有,我怎样才能实现这种行为?
我希望我可以通过标志告诉complete哪个目录用作基本目录,但我看到的与目录相关的唯一标志是-dwhich 与 相同-A directory,它生成目录列表。
有趣的是,如果我使用compgen -f "~/proposals/",它会列出 中的文件和目录~/proposals:
$ pwd
/home/user/any/directory/it/should/not/matter
$ compgen -f "~/proposals/"
~/proposals/job_01
~/proposals/proposal_01
~/proposals/proposal_02
Run Code Online (Sandbox Code Playgroud)
我见过这个问题,但是:
CDPATH会给其他命令带来更多混乱。compgen也不适用于嵌套目录。我尝试并找到了一些如何修复它的方法和想法。
专业人士可以改进我的方式并创建更好/完美的解决方案。
我的系统是 Debian GNU/Linux 10 (buster) 4.19.0-16-amd64,带有 KDE 和 GNOME
第一部分:
启动一个新的外壳
创建工作目录/home/user/ComBash并cd进入其中
创建一个脚本,mytab我们将这个脚本绑定到完整的命令
现在mytab看起来像:
#!/bin/bash
echo "MYTAB"
Run Code Online (Sandbox Code Playgroud)
chmod +x mytab
px为完整命令创建第二个脚本
现在px看起来像:
#/usr/bin/env bash
echo "PX"
Run Code Online (Sandbox Code Playgroud)
chmod +x px
现在我们开始我们的px脚本
source px
Run Code Online (Sandbox Code Playgroud)
或者
./px
Run Code Online (Sandbox Code Playgroud)
或者
. ./px
Run Code Online (Sandbox Code Playgroud)
输出应该是“PX”(它有效)
bin/创建一个名为in的新文件夹/home/user/ComBash
mkdir bin
Run Code Online (Sandbox Code Playgroud)
我们的文件现在是
mytab | script
px | script
bin/ | folder
Run Code Online (Sandbox Code Playgroud)
现在安装mytab在bin/我们的workdir | 路径中 /home/user/ComBash/bin并mytab删除/home/user/ComBash/
install mytab bin/mytab && rm mytab
Run Code Online (Sandbox Code Playgroud)
现在将workdirbin/文件夹添加到$PATH
PATH="/home/user/ComBash/bin:${PATH}"
Run Code Online (Sandbox Code Playgroud)
或者
PATH="${PATH}:/home/user/ComBash/bin"
Run Code Online (Sandbox Code Playgroud)
检查与
echo $PATH
Run Code Online (Sandbox Code Playgroud)
检查是否mytab有效:
myt+TAB并按Entermytab按Enter在文件夹内创建一些文件夹、子文件夹和空文件,我们需要这些文件夹和文件来检查TAB+是否TAB有效并检查 TAB|TAB 显示的内容
现在我们有了第二部分的结构,该解决方案仅适用于当前 shell
如果我们关闭并启动一个新的 shell,/home/user/ComBash/binin$PATH被删除并且 bash 找不到mytab中的脚本/home/user/ComBash/bin,那么每次启动新 shell 时都必须重复步骤 9.(设置 $PATH)。
如果您不想每次启动 shell 时都重复步骤 9,则可以永久添加/home/user/ComBash/bin。$PATH
第二部分:
打开并编辑px文件
我也尝试了很多这个命令,但我现在不会解释它们,你可以尝试查看结果,只需取消注释并编辑你想尝试的行。
现在 px 看起来像:
#/usr/bin/env bash
#complete -f mytab
#complete -D -F "/home/user/ComBash" mytab
#complete -W "$(find /home/user/ComBash/ -path "" -prune -o \( -type d -ls \) -o \( -type f -ls \) | cut -d/ -f 5-)" mytab
#complete -W "$(find /home/user/ComBash/ -path "" -prune -o \( -type d -ls \) -o \( -type f -ls \) | cut -d/ -f 2- | sed 's/$/\//')" mytab
#complete -W "$(find /home/user/ComBash/ -path "" -prune -o \( -ls \)))" mytab
#complete -W "$(ls -R ${MYPATH} | grep /)" mytab
MYPATH="/home/user/ComBash/"
complete -W "$(ls -R ${MYPATH})" mytab
Run Code Online (Sandbox Code Playgroud)
我们将完整的命令绑定到mytab脚本中
-W意味着我们给出完整的单词列表
我们得到带有 的单词列表ls -R。
ls -R列出给定路径中的所有文件、子文件、目录和子目录
我们启动 px 脚本
source px
Run Code Online (Sandbox Code Playgroud)
每次我们在脚本中进行更改时,都必须重新启动脚本(请参阅第 I 部分中的步骤 6)
source px
Run Code Online (Sandbox Code Playgroud)
现在我们在 shell 中使用
mytab+TAB
/home/user/ComBash/我们可以看到给定路径 ( )中所有文件、子文件、目录和子目录的列表
我们可以选择每个文件、子文件、目录和子目录,并使用 [TAB] 自动完成
选择有效的子文件夹和 [TAB]
如果我们按下Enter脚本mytab将回显“MYTAB”
mytab让我们在 中编辑脚本/home/user/ComBash/bin。
现在mytab看起来像:
#!/bin/bash
MYPATH=/home/user/ComBash
# echo $MYPATH
echo $1
DATA=$(find ${MYPATH} -name ${1})
echo $DATA
####### DO SOMETHING #######
Run Code Online (Sandbox Code Playgroud)
$1px输出我们从脚本
搜索中收到的文件夹或文件DATA,并输出PATH文件夹或文件的
现在我们可以对当前文件或文件夹执行某些操作
mytab+Tab按Enter