0

I have some directories with music files

$ 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 

and a script

$ 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} $ 

When I cd ~/Music and use completions, then my command works as intended; when I execute it from a generic directory it does not work, as the completion (at its best) places the full path names on the command line.

How can I convince bash/readline to complete on directories/subdirectories rooted in ~/Music, without placing the full path name on the command line?


I have read autocomplete command from a certain folder and Bash autocomplete: List files and directories from other directory.

In the first case, the command take a single argument, in the second case the full path name is placed on the command line and it cannot complete on subdirectories.

Following a suggestion in a comment, I've implemented what is suggested here, but completing after pmds would list all the executables in my system, and if I execute the command anyway, I'm teletransported to ~/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 $ 
2
  • There's nothing in unix.stackexchange.com/a/630139/70524 that restricts it to one argument. Using the example there go one-arg <tab> works just fine. If you did try it and could only complete one argument, show us the actual code you used. Commented Feb 20, 2024 at 11:02
  • @muru I tried to follow your advice, but I probably made a mistake Commented Feb 23, 2024 at 20:00

2 Answers 2

1

Experimenting a bit, there's an even simpler way using complete -C. Define a function that writes out the directory names for completion to the output:

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

Then:

complete -C _pmd -o filenames pmd 

-C runs the _pmd in a subshell, so we don't need to restore the working directory (a problem with the solution in this answer - which didn't affect that user since their command changed the directory in the end anyway). Nor do we need to worry about resetting nullglob. Using -o filenames also allows readline to quote the completion appropriately if you've directory entries with special characters in them. While a subshell is used, everything else here is built-in to the shell, so we save the cost of forking and running an external command.

0

I realized it's simpler... In the end I added a completion function to my ~/.bashrc and binded it to my command name

$ 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 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.