我想要“自动完成”以固定目录为根的子目录和子/子目录

我想要“自动完成”以固定目录为根的子目录和子/子目录

我有一些包含音乐文件的目录

$ tree -d ~/Music/
/home/boffi/Music/
├── Aldous_Harding
│   ├── Aldous_Harding
│   ├── Designer
│   ├── Party
│   └── Warm_Chris
├── Madness
│   └── The_Very_Best
└── Mitski
    ├── Be_the_Cowboy
    ├── Bury_Me_At_Makeout_Creek
    ├── Laurel_Hell
    ├── Lush
    ├── Puberty_2
    ├── Retired_from_Sad,_New_Career_in_Business
    └── The_Land_Is_Inhospitable_and_So_Are_We

和一个脚本

$ cat ~/bin/pmd
# Play Music Directories

root=/home/boffi/Music/
list_of_dirs=""
for dir in $@ ; do
  list_of_dirs=${list_of_dirs}" ${root}$dir"
done
list_of_files=$( find ${list_of_dirs} | shuf )
echo mpv -no-terminal -no-video ${list_of_files}
$

当我cd ~/Music使用补全时,我的命令将按预期工作;当我从通用目录执行它时,它不起作用,因为完成(最好)将完整路径名放在命令行上。

如何说服 bash/readline 完成以 为根的目录/子目录~/Music,而不将完整路径名放在命令行上?


我读过了来自某个文件夹的自动完成命令Bash 自动完成:列出其他目录中的文件和目录

在第一种情况下,该命令采用单个参数,在第二种情况下,完整路径名放置在命令行上,并且不能在子目录上完成。

遵循建议在评论中,我已经实现了建议的内容这里,但完成后pmds会列出我系统中的所有可执行文件,如果我无论如何执行该命令,我会被传送到~/Music

$ pwd
/home/boffi
$ tail -3 .bashrc
alias yt="yt-dlp -f 'bestvideo[height<=?720]+bestaudio/best' -write-sub --write-auto-sub --sub-lang 'en.*' -o"

. /home/boffi/script
$ cat script
#!/usr/bin/bash

pmds () { echo /home/boffi/Music/$1 ; }
goM ()  { cd /home/boffi/Music ; }
complete -s -F goM pmds

$ . .bashrc
$ pmds <TAB>
Display all 6241 possibilities? (y or n)
$ pmds pippo
/home/boffi/Music/pippo
$ pwd
/home/boffi/Music
$ 

答案1

尝试一下,有一种更简单的方法,使用complete -C.定义一个函数,将目录名称写出以完成输出:

_pmd () {
  shopt -s nullglob
  cd /home/boffi/Music
  # $2 is the word being completed
  printf "%s\n" "$2"*/   # The trailing `/` restricts matches to directories.
}

然后:

complete -C _pmd -o filenames pmd

-C运行_pmd,因此我们不需要恢复工作目录(解决方案中的问题这个答案- 这不会影响该用户,因为他们的命令最终更改了目录)。我们也不需要担心重置nullglob。使用-o filenames如果目录条目中包含特殊字符,还允许 readline 适当地引用完成内容。当使用子 shell 时,这里的其他所有内容都是内置于 shell 中的,因此我们节省了分叉和运行外部命令的成本。

答案2

我意识到它更简单......最后我添加了一个完成函数~/.bashrc并将其绑定到我的命令名称

$ tail .bashrc

_pmd()
{   local cur opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    opts=$( cd /home/boffi/Music/ ; find * -type d | sed 's.$./.' )
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
}
complete -F _pmd pmd

$ pmd <TAB>
Aldous_Harding/
Aldous_Harding/Aldous_Harding/
Aldous_Harding/Designer/
Aldous_Harding/Party/
Aldous_Harding/Warm_Chris/
Madness/
Madness/The_Very_Best/
Mitski/
Mitski/Be_the_Cowboy/
Mitski/Bury_Me_At_Makeout_Creek/
Mitski/Laurel_Hell/
Mitski/Lush/
Mitski/Puberty_2/
Mitski/Retired_from_Sad,_New_Career_in_Business/
Mitski/The_Land_Is_Inhospitable_and_So_Are_We/
$ pmd 

相关内容