问题
I have a shell script (which I source into .bashrc) that allows me to jump to my projects directory from anywhere.
cdp(){
proj="~/dev/projects/$@/"
builtin cd $proj
}
_my_cdp()
{
local cur opts
cur="${COMP_WORDS[COMP_CWORD]}"
opts=$(ls ~/dev/projects/)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
}
complete -o nospace -F _my_cdp cdp
The problem is, the cd
on line 3 says:
bash: cd: ~/dev/projects/jsonparse/: No such file or directory
Here is the full console output showing the error and proving the directory exists.
amflare:~$ cd dev/projects/ (go to dir)
amflare:~/dev/projects$ ls -al (look at contents)
total 68
drwxrwxr-x 17 www-data amflare 4096 Dec 29 13:11 .
drwxrwxr-x 4 amflare amflare 4096 Dec 6 17:32 ..
drwxrwxr-x 3 www-data amflare 4096 Dec 22 17:33 bot
drwxrwxr-x 3 www-data amflare 4096 Dec 20 15:17 jsonparse
drwxrwxr-x 3 www-data amflare 4096 Dec 28 19:58 magic
drwxrwxr-x 2 www-data amflare 4096 Nov 11 14:42 test
amflare:~/dev/projects$ cd (go to home)
amflare:~$ cdp (run autocomplete)
bot jsonparse magic test
amflare:~$ cdp jsonparse (pick target)
bash: cd: ~/dev/projects/jsonparse/: No such file or directory
amflare:~$ (still in home)
I've tried everything I can think of and a few things google gave back for other distros (I'm on Ubuntu Gnome 16.04). No matter what I do, the shell script will not acknowledge the existence of anything inside ~/dev/projects/
. Additionally, it does not work when I have the functions in .bashrc
itself, so I don't think it is a subshell problem. Please let me know if you need any more information. Thanks.
回答1:
That's because the tilde isn't expanded. Use proj=~/"dev/projects/$@/"
with the tilde out of the quotes. Or use the variable HOME
: proj="$HOME/dev/projects/$@"
. Note, though, that using $@
is not really good. What do you want if there are several arguments?
Also, don't use opts=$(ls ~/dev/projects/)
. Use compgen
directly like so:
cdp() {
local proj=~/dev/projects/
builtin cd "$proj$1"
}
_my_cdp() {
local proj=~/dev/projects/
local i p
COMPREPLY=()
while IFS= read -r i; do
printf -v p '%q' "${i#"$proj"}"
COMPREPLY+=( "$p" )
done < <(compgen -d -- "$proj$2")
}
When completing, the completion function _my_cdp
will have as parameter $2
the word being completed; we give that to compgen -d
(with the prefix $proj
), and loop through the results (the results are output one per line—so yeah, it'll break if you have newlines in your directories). With each name found, we quote it using printf '%q'
, while using a parameter expansion to remove the prefix $proj
. The quoting is used so as not to break if directory name contains spaces or funny characters (e.g., glob characters), and we populate the array COMPREPLY
one term at a time. That's a rather robust way to deal with completion (yet not 100% unbreakable, but it'll do the job for your non-crazy directory names!).
来源:https://stackoverflow.com/questions/41400557/shell-script-thinks-directory-does-not-exist-when-running-cd