Shell脚本认为运行cd时目录不存在

Shell脚本认为运行cd时目录不存在

本文介绍了Shell脚本认为运行cd时目录不存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个shell脚本(我从.bashrc中获取了该脚本),该脚本可让我从任何地方跳转到我的项目目录.

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

问题是,第3行上的cd说:

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)

我已经尝试了所有我能想到的东西,以及google还给其他发行版的一些东西(我在Ubuntu Gnome 16.04上).无论我做什么,shell脚本都不会承认~/dev/projects/内部是否存在任何内容.另外,当我具有.bashrc本身的功能时,它不起作用,因此,我认为这不是subshel​​l问题.如果您需要更多信息,请告诉我.谢谢.

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.

推荐答案

这是因为波浪线没有展开.使用proj=~/"dev/projects/$@/",将引号引起来.或使用变量HOME:proj="$HOME/dev/projects/$@".但是请注意,使用$@并不是很好.如果有几个参数,您想要什么?

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?

此外,请勿使用opts=$(ls ~/dev/projects/).像这样直接使用compgen:

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")
}

完成时,完成功能_my_cdp将具有要完成的单词作为参数$2;我们将其提供给compgen -d(前缀为$proj),并循环遍历结果(结果每行输出一个,所以,是的,如果目录中有换行符,它将中断).对于找到的每个名称,我们都使用printf '%q'对其进行引用,同时使用参数扩展来删除前缀$proj.如果目录名称包含空格或有趣的字符(例如,glob字符),则使用引号以免引起混乱,并且我们一次将一个术语填充到数组COMPREPLY中.这是处理完成的一种相当健壮的方法(尽管不是100%不可破坏的,但是它将为您的非疯狂目录名做好工作!).

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!).

这篇关于Shell脚本认为运行cd时目录不存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 03:43