2016-12-30 66 views
4

我有一個shell腳本(我將其導入到.bashrc中),它允許我從任何地方跳到我的項目目錄。Shell腳本在運行時認爲目錄不存在

cdp(){ 
    proj="~/dev/projects/[email protected]/" 
    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本身的功能時,它不起作用,所以我不認爲它是一個子外殼問題。如果您需要更多信息,請告訴我。謝謝。

+0

這是因爲代字號未擴展。使用'proj =〜/「dev/projects/$ @ /」',並用引號括起來。或者使用變量'HOME':'proj =「$ HOME/dev/projects/$ @」'。請注意,使用'$ @'並不是很好。如果有幾個參數,你想要什麼? –

+0

考慮通過http://shellcheck.net/運行此代碼 - 有*很多*錯誤;這可能無法抓住所有東西,但這是一個開始的地方。 –

+0

...見,f/e,[ParsingLs](http://mywiki.wooledge.org/ParsingLs) - 'ls'是程序使用不當的工具。而且缺乏引用導致它自己的問題。 –

回答

5

這是因爲代字號未擴展。使用proj=~/"dev/projects/[email protected]/",並用引號括起來。或使用變量HOMEproj="$HOME/dev/projects/[email protected]"。但請注意,使用[email protected]並不是很好。如果有幾個參數,你想要什麼?另外,請勿使用opts=$(ls ~/dev/projects/)。直接使用compgen像這樣:

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%不可破解的,但它會爲你的非瘋狂目錄名稱做這項工作!)。

+0

這是問題所在。謝謝。至於$ @,我基於這個別人的代碼,並沒有打擾改變它。我現在雖然。 – amflare

+1

@tbirrell:回答編輯略有更好的完成! –

+0

啊。乾杯!我實際上正在試圖弄清楚這一點。這裏有很多移動部件,我不明白。編碼高爾夫球風格是否會讓球迷難以接受? – amflare