2009-09-08 84 views

回答

3

很簡單的東西和天真:

echo "$PATH"|grep -q whatever && echo "found it" 

無論在哪裏就是你要搜索的內容。您可以將$?放入一個變量中,或使用正確的if語句代替&&

限制包括:

  • 以上將匹配的更大的路徑子(試穿「bin」的匹配,它可能會發現,儘管「斌」是不是在你的路徑,/斌和/ usr/bin中是)
  • 以上將不自動擴展類似於快捷〜

或使用Perl的一個班輪:

perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it" 

這仍然有限制,它不會做任何shell擴展,但它不會失敗,如果子字符串匹配。 (以上匹配「/usr/bin」,如果不清楚的話)。

+1

在JasonWoof的回答中匹配到行首和冒號的開始/結尾處理您的子字符串匹配限制。 Tilde擴展不是一個常見問題,因爲大多數人在分配時允許擴展它(例如'PATH =「〜/ bin:$ PATH」'),但如果需要可以用替換來處理。 – Cascabel 2009-09-08 21:33:31

+2

不錯,有人在3.5年後低估了這一點。並沒有留下評論。瘸。 – 2013-03-29 16:04:47

+0

我正在使用grep解決方案用冒號包裝模式。 – elias 2015-03-09 17:44:12

102

使用grep是矯枉過正的,如果您正在搜索包含RE元字符的任何內容,可能會導致麻煩。這個問題可以使用bash的內置命令[[來解決得很好:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then 
    echo "Your path is correctly set" 
else 
    echo "Your path is missing ~/bin, you might want to add it." 
fi 

注意,$ PATH的兩膨脹和搜索路徑之前添加冒號解決了子字符串匹配問題;雙引號路徑避免了元字符的問題。

+4

如果'$ HOME/bin'在'$ PATH'的開頭或末尾,那末在每一端都不可能有冒號。 – 2009-09-09 04:44:40

+8

我不確定我是否理解你的反對意見。例如,如果$ PATH是/ usr/bin:/ bin:/ usr/sbin:/ sbin:/ home/fred/bin,那麼「:/ usr/bin:/ bin:/ usr/sbin:/ sbin:/ home/fred/bin:「會匹配*」:/ home/fred/bin:「*就好了。 – 2009-09-09 07:18:57

+6

你說得對。我沒有看到「$ PATH」附近冒號的作用。抱歉。 – 2009-09-09 13:56:50

10

這裏是如何做到這一點不grep

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]] 

的這裏關鍵是使冒號和使用?()結構通配符可選。不應該有在這種形式的元字符的任何問題,但如果你希望包括引號,這是他們到何處去:

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]] 

這是另一種方式來做到這一點使用匹配運算符(=~)這樣的語法更像是grep的:

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]] 
+0

'?(:*)'是一個[擴展glob](https://mywiki.wooledge.org/glob#extglob)模式,需要在大多數平臺上分別明確啓用('shopt -s extglob')。 – tripleee 2018-01-10 11:09:15

0

$PATH是描述一個目錄列表由:分隔字符串列表。目錄是由/分隔的字符串列表。兩個不同的字符串可能指向相同的目錄(如$HOME~/usr/local/bin/usr/local/bin/)。所以我們必須修正我們想要比較/檢查的規則。我建議比較/檢查整個字符串,而不是物理目錄,但刪除重複和尾隨/

先刪除重複和$PATH尾隨/

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' 

現在假設$d包含要檢查的目錄。然後輸入前面的命令來檢查$d中的$PATH

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' | grep -q "^$d$" || echo "missing $d" 
0

我寫了下面的shell功能,如果一個目錄在當前PATH上市報告。這個函數是POSIX兼容的,並且可以在Dash和Bash等兼容的shell中運行(不依賴於Bash特有的功能)。

它包括將相對路徑轉換爲絕對路徑的功能。它使用readlinkrealpath實用程序,但如果提供的目錄沒有..或其他鏈接作爲其路徑的組件,則不需要這些工具。除此之外,該功能不需要任何外殼程序。

# Check that the specified directory exists – and is in the PATH. 
is_dir_in_path() 
{ 
    if [ -z "${1:-}" ]; then 
    printf "The path to a directory must be provided as an argument.\n" >&2 
    return 1 
    fi 

    # Check that the specified path is a directory that exists. 
    if ! [ -d "$1" ]; then 
    printf "Error: ‘%s’ is not a directory.\n" "$1" >&2 
    return 1 
    fi 

    # Use absolute path for the directory if a relative path was specified. 
    if command -v readlink >/dev/null ; then 
    dir="$(readlink -f "$1")" 
    elif command -v realpath >/dev/null ; then 
    dir="$(realpath "$1")" 
    else 
    case "$1" in 
     /*) 
     # The path of the provided directory is already absolute. 
     dir="$1" 
     ;; 
     *) 
     # Prepend the path of the current directory. 
     dir="$PWD/$1" 
     ;; 
    esac 
    printf "Warning: neither ‘readlink’ nor ‘realpath’ are available.\n" 
    printf "Ensure that the specified directory does not contain ‘..’ in its path.\n" 
    fi 

    # Check that dir is in the user’s PATH. 
    case ":$PATH:" in 
    *:"$dir":*) 
     printf "‘%s’ is in the PATH.\n" "$dir" 
     return 0 
     ;; 
    *) 
     printf "‘%s’ is not in the PATH.\n" "$dir" 
     return 1 
     ;; 
    esac 
} 

使用:$PATH:的部分確保了圖案也匹配,如果所期望的路徑是在PATH第一或最後一個條目。這個巧妙的技巧是基於this answer by Glenn Jackman on Unix & Linux

0

絕對沒有必要使用像grep這樣的外部工具。這是我一直在使用的,它應該可以移植回Bourne shell的舊版本。

case :$PATH: # notice colons around the value 
    in *:$HOME/bin:*) ;; # do nothing, it's there 
    *) echo "$HOME/bin not in $PATH" >&2;; 
esac 
相關問題