2014-05-17 86 views
1

我正在編寫一個腳本,用於檢查相對於腳本工作目錄的文件夾是否位於shell的路徑中。從路徑中刪除底層

例如,如果項目結構是:

top/ 
bin/ 
tests/ 
    test1/ 
    foo.sh 
    test2/ 
    foo.sh 

我要檢查,如果top/binPATH無論從foo.sh。我知道下面的工作:

cd ../../bin 
if echo $PATH|grep `pwd`; then 
    echo "Success" 
else 
    echo "Failure" 
fi 

但我必須跟蹤哪個目錄的,我開始在這樣我就可以cd回到那裏。我可以在pwd之後切斷最後兩個目錄,然後再附加bin到那個嗎?有沒有其他智能的方法來處理這個問題? 作爲獎勵,我想讓這個腳本在tests內的其他目錄級別強健,但如果它使事情複雜化,這並不是必須的。根據需要

+0

你可以使用子串操作和通配符做 – technosaurus

+1

一個方便的技術來避免以往任何時候都需要到CD回是簡單地在子shell中運行。例如,將命令封裝在parens中:'(cd ../../bin || exit 1; echo $ PATH | tr:\\ n | grep -q $(pwd))&& echo Success ||回聲失敗' –

+0

@WilliamPursell偉大的提示,我不知道!有點像elisp中的save-excursion – jake

回答

2
# Exits with code 0 if the first argument is on the user's path. 
is_on_path() { 
    CANONICAL_NAME=$(readlink -f "$1") 
    while read -r -d: COMPONENT; do 
    if [[ "$CANONICAL_NAME" = "$COMPONENT" ]]; then 
     return 0 
    fi 
    done <<< "$PATH" 
    return 1 
} 
  • readlink -f將評估路徑組件,如../..
  • read -r -d: COMPONENT將從其輸入中讀取冒號分隔的參數列表,並將其寫入COMPONENT變量。
  • <<< "$PATH"會在系統路徑中傳入while的標準輸入。

現在你可以調用,像這樣:

if is_on_path "../../bin"; then 
    echo "Success!" 
else 
    echo "Failure!" 
fi 

獎勵:從這裏它很容易遞歸這適用於所有的父目錄:

find_matching_ancestor() { 
    current_dir=$(pwd) 
    while [[ "$current_dir" != "/" ]]; do 
    if is_on_path "$current_dir/bin"; then 
     echo "$current_dir" 
     return 0 
    fi 
    current_dir=$(dirname "$current_dir") 
    done 
    return 1 
} 
+0

你使用while循環和'dirname'的解決方案正是我所需要的。 – jake

0

這似乎是工作

echo $PATH | xargs -d: -n1 | grep ^$(readlink -f ../../bin)$ | wc -l 
+0

請注意,'-d'是[非POSIX擴展名](http://www.unix.com/man-page/POSIX/0/xargs/),在BSD'xargs'中不存在(如Mac OS中X)。 –

0

也許最可靠的方法是將可執行位設置爲該目錄的文件並使用「which」。

例如,我的PATH上是/ bin?

which ls 
/bin/ls