固定ディレクトリにルートがあるサブディレクトリとサブディレクトリを「自動完成」したいと思います。

固定ディレクトリにルートがあるサブディレクトリとサブディレクトリを「自動完成」したいと思います。

音楽ファイルを含むディレクトリがいくつかあります。

$ 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コマンドは期待どおりに機能します。汎用ディレクトリで実行すると、完了機能はコマンドラインにフルパス名を入力するため機能しません。

~/Musicコマンドラインにフルパス名を入力せずにルートとしてディレクトリ/サブディレクトリを完了するようにbash / readlineをどのように説得できますか?


私が読んでフォルダのオートコンプリートコマンドそして Bashオートコンプリート:他のディレクトリのファイルとディレクトリの一覧表示

最初の場合、コマンドは単一の引数を使用し、2番目の場合、フルパス名はコマンドラインに配置され、サブディレクトリでは実行できません。

アドバイスに従うコメントで提案した内容を実装しました。ここしかし、完了すると、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が適切に完成を引用することを許可します。サブシェルを使用すると、ここの他のすべてがシェルに組み込まれるため、外部コマンドを分岐して実行するコストが節約されます。

答え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 

関連情報