complete -o filenames incorrectly adds slashes after directory names
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
bash-completion (Ubuntu) |
New
|
Undecided
|
Unassigned |
Bug Description
I have a Bash application where I need to complete filenames and directory names that exist in another directory relative to the current directory. In the completion list shown in the terminal after I press TAB, I would like to see directory names with a slash after the name, and filenames with no slash after. This will help the user to distinguish between directory names and filenames.
As I understand it, there are two ways to achieve this:
a) either use 'complete -o nospace', or
b) use 'complete -o filenames -o nospace'
For option a), there is a problem as soon as the depth of the path exceeds 1. For example: If I have directories
- a/b/c
- a/b/d
I will, after pressing TAB in the terminal window get
$ cmd a/
b/c b/d
so the completion list will be 'b/c', 'b/d' instead of the less verbose 'c', 'd' (which is also desired, and also how 'complete -o filenames' works..)
For option b) , the problem is that 'complete -o filenames' will add slashes after completion words that exist as directory names in the current directory. This is of course, correct if you try to complete names in the current directory, but if the completion words are taken from another directory, this can lead to either multiple slashes (two slashes) after directory names, or to filenames with trailing slashes ( a filename should of course not have a trailing slash after it).
Here is an example, that I hope will illustrate the problems:
First generate some dummy directories and files:
$ mkdir a
$ touch b
$ mkdir c
$ mkdir dir1
$ touch dir1/a
$ mkdir dir1/b
$ mkdir dir1/c
$ mkdir dir1/b/c
$ mkdir dir1/b/d
Then consider the following completion setup:
$ cat setup
_my_test1() {
local cur comp_dir
cur=
comp_dir="$PWD"
COMPREPLY=( $( cd "$comp_dir"; compgen -f "$cur" ) )
}
complete -o filenames -o nospace -F _my_test1 test1
_my_test2() {
local cur comp_dir
cur=
comp_
COMPREPLY=( $( cd "$comp_dir"; compgen -f "$cur" ) )
}
complete -o filenames -o nospace -F _my_test2 test2a
complete -S '/' -o nospace -F _my_test2 test2b
_my_test3() {
local cur comp_dir temp word
cur=
comp_
temp=( $(cd "$comp_dir"; compgen -f "$cur") )
COMPREPLY=()
for word in "${temp[@]}" ; do
[[ -d "$comp_dir/$word" ]] && word="$word/"
COMPREPLY+=( "$word" )
done
}
complete -o nospace -F _my_test3 test3
_my_test4() {
local cur comp_dir temp word
cur=
comp_
temp=( $(cd "$comp_dir"; compgen -f "$cur") )
COMPREPLY=()
for word in "${temp[@]}" ; do
[[ -d "$comp_dir/$word" ]] && word="$word/"
COMPREPLY+=( "$word" )
done
}
complete -o filenames -o nospace -F _my_test4 test4
_my_test5() {
local cur comp_dir temp word
cur=
comp_
temp=( $(cd "$comp_dir"; compgen -f "$cur") )
COMPREPLY=()
for word in "${temp[@]}" ; do
[[ -d "$comp_dir/$word" ]] && word="$word/"
[[ -d "$word" ]] && word="${word%/}"
COMPREPLY+=( "$word" )
done
}
complete -o filenames -o nospace -F _my_test5 test5
Then source the file in the Bash terminal window:
$ . setup
Then:
- 'test1': will complete correctly in the current directory. This example is just to show how the completion should work when the directory to complete in, is different from the current directory.
- 'test2a': will not add slashes after directory names in 'dir1', but will incorrectly add slashes after directory names that also exist in the current directory.
- 'test2b' : Investigates how 'complete -o nospace' works without '-o filenames' option
- 'test3' : Same as 'test2b', but also manually adds slashes after directory names in 'dir1'.. (but still leads to the verbose completion lists described above in a))
- 'test4' : same as 'test2a', but also manually adds slashes after directory names in 'dir1',
but still unwanted slashes are added after names that also exist in the current directory
- 'test5' : Same as 'test4' but also tries to trick Bash completion, by removing slashes from names that also exists in the current directory. Notice that still there is no way to avoid the incorrect slash after the file 'a' in 'dir1'. The reason is that the name 'a' also exists as a directory name in the current directory..
$ lsb_release -rd
Description: Ubuntu 14.04.2 LTS
Release: 14.04
$ apt-cache policy bash-completion
bash-completion:
Installed: 1:2.1-4
Candidate: 1:2.1-4
Version table:
*** 1:2.1-4 0
500 http://
100 /var/lib/