Shell 当 运行 cd 时,脚本认为目录不存在
Shell Script thinks directory does not exist when running cd
我有一个 shell 脚本(我将其源代码放入 .bashrc),它允许我从任何地方跳转到我的项目目录。
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
问题是,第 3 行的 cd
说:
bash: cd: ~/dev/projects/jsonparse/: No such file or directory
这是显示错误并证明目录存在的完整控制台输出。
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)
我已经尝试了所有我能想到的东西,并且一些东西 google 回馈给了其他发行版(我在 Ubuntu Gnome 16.04 上)。无论我做什么,shell 脚本都不会承认 ~/dev/projects/
中任何东西的存在。另外,当我在 .bashrc
本身有函数时它不起作用,所以我不认为这是一个 subshell 问题。如果您需要更多信息,请告诉我。谢谢。
那是因为波浪号没有展开。在引号外使用 proj=~/"dev/projects/$@/"
和波浪号。或者使用变量HOME
:proj="$HOME/dev/projects/$@"
。但是请注意,使用 $@
并不是很好。如果有多个参数,你想要什么?
另外,不要使用 opts=$(ls ~/dev/projects/)
。像这样直接使用 compgen
:
cdp() {
local proj=~/dev/projects/
builtin cd "$proj"
}
_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")
}
完成时,完成函数_my_cdp
将把正在完成的单词作为参数</code>;我们将其提供给 <code>compgen -d
(前缀为 $proj
),并循环遍历结果(每行输出一个结果——所以是的,如果你的目录中有换行符,它就会中断)。找到每个名称后,我们使用 printf '%q'
引用它,同时使用参数扩展删除前缀 $proj
。如果目录名称包含空格或有趣的字符(例如,glob 字符),使用引号是为了不中断,我们一次填充数组 COMPREPLY
一个术语。这是处理完成的一种相当稳健的方法(但不是 100% 牢不可破,但它会为您的非疯狂目录名称完成工作!)。
我有一个 shell 脚本(我将其源代码放入 .bashrc),它允许我从任何地方跳转到我的项目目录。
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
问题是,第 3 行的 cd
说:
bash: cd: ~/dev/projects/jsonparse/: No such file or directory
这是显示错误并证明目录存在的完整控制台输出。
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)
我已经尝试了所有我能想到的东西,并且一些东西 google 回馈给了其他发行版(我在 Ubuntu Gnome 16.04 上)。无论我做什么,shell 脚本都不会承认 ~/dev/projects/
中任何东西的存在。另外,当我在 .bashrc
本身有函数时它不起作用,所以我不认为这是一个 subshell 问题。如果您需要更多信息,请告诉我。谢谢。
那是因为波浪号没有展开。在引号外使用 proj=~/"dev/projects/$@/"
和波浪号。或者使用变量HOME
:proj="$HOME/dev/projects/$@"
。但是请注意,使用 $@
并不是很好。如果有多个参数,你想要什么?
另外,不要使用 opts=$(ls ~/dev/projects/)
。像这样直接使用 compgen
:
cdp() {
local proj=~/dev/projects/
builtin cd "$proj"
}
_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")
}
完成时,完成函数_my_cdp
将把正在完成的单词作为参数</code>;我们将其提供给 <code>compgen -d
(前缀为 $proj
),并循环遍历结果(每行输出一个结果——所以是的,如果你的目录中有换行符,它就会中断)。找到每个名称后,我们使用 printf '%q'
引用它,同时使用参数扩展删除前缀 $proj
。如果目录名称包含空格或有趣的字符(例如,glob 字符),使用引号是为了不中断,我们一次填充数组 COMPREPLY
一个术语。这是处理完成的一种相当稳健的方法(但不是 100% 牢不可破,但它会为您的非疯狂目录名称完成工作!)。