$ PWDが指定されたパスのサブディレクトリであるかどうかを確認する方法


25

たとえば$PWD、/ homeのサブディレクトリであるかどうかを確認します。つまり、ある文字列が別の文字列で始まるかどうかを確認するために、bash文字列操作を検索しています。

回答:


26

ディレクトリが別のディレクトリのサブディレクトリであるかどうかを確実にテストする場合は、単なる文字列プレフィックスチェック以上のものが必要になります。Gillesの回答では、このテストを適切に行う方法について詳しく説明しています。

ただし、単純な文字列プレフィックスチェックが必要な場合(パスを既に正規化している場合がありますか?)、これは良い方法です。

test "${PWD##/home/}" != "${PWD}"

$PWD「/ home /」で始まる場合、左側で削除されます。つまり、右側と一致しないため、「!=」はtrueを返します。


1
完璧な+1、[ "${PWD##$VAR}" != "$PWD" ]そしてより一般的な場合:そして、これが[code-golf](stackoverflow.com/questions/tagged/code-golf)の質問であれば、2文字で私をbeatられたでしょう;-)より読みやすい...
トビアスキーンツラー

FWIW、これはまた有用かもしれません:${PWD/#$HOME/\~}
user1338062

わかりましたが、PWD = "/ home /../ etc /"はどうですか
Alexis Peters

1
@AlexisPeters:そのとおりです。私は質問の「文字列プレフィックス」部分に焦点を当てていましたが、それをより明確にするために編集しました。Gillesは、サブディレクトリをチェックする適切な方法をうまくカバーしています。
ジャンダー

1
%%は文字列の先頭ではなく末尾からキャプチャ"${PWD%%/subdir*}"するため、ユーザーが現在subdirのサブディレクトリにいるか、サブディレクトリにいるかを検出するために使用しますsubdir。これは、パラメータの置換に関する詳細情報を探している人にとって有用です:tldp.org/LDP/abs/html/parameter-substitution.html
ジョージパンタ

33

Bourneスタイルのシェルで、文字列が別の文字列のプレフィックスかどうかをテストするには:

case $PWD/ in
  /home/*) echo "home sweet home";;
  *) echo "away from home";;
esac

同じ原則が接尾辞または部分文字列のテストにも機能します。case構文では、ファイル名とは異なり、*a /やinitial を含む任意の文字に一致することに注意してください.

[[ … ]]構文(bash、ksh、zshなど)を実装するシェルでは、文字列をパターンと照合するために使用できます。(この[コマンドは文字列の等価性のみをテストできることに注意してください。)

if [[ $PWD/ = /home/* ]]; then 

現在のディレクトリがその下/homeにあるかどうかを具体的にテストしている場合、シンボリックリンクのため、単純なサブストリングテストでは不十分です。

/home独自のファイルシステムである場合、現在のディレクトリ(.)がそのファイルシステム上にあるかどうかをテストします。

if [ "$(df -P . | awk 'NR==2 {print $6}')" = "/home" ]; then
  echo 'The current directory is on the /home filesystem'
fi

NetBSD、OpenBSD、またはGNU(Linux)readlinkを使用readlink -fしている場合、シンボリックリンクをパスから削除するために使用できます。

case $(readlink -f .)/ in $(readlink -f /home)/*) 

それ以外の場合はpwd、現在のディレクトリを表示するために使用できます。ただし、シェルがcdコマンドを追跡し、「実際の」場所ではなく、ディレクトリに到達するために使用した名前を保持している場合は、組み込みのシェルを使用しないように注意する必要があります。

case $(pwd -P 2>/dev/null || env PWD= pwd)/ in
  "$(cd /home && { pwd -P 2>/dev/null || env PWD= pwd; })"/*) 

+1この包括的な回答をありがとう。私はこれを尋ねる際にリンクとファイルシステムの特性を考慮しませんでしたが、知っておくのは間違いなく良いです
トビアスキンツラー

8

原油バージョン:

[ ${PWD:0:6} = "/home/" ]

最初に文字を数える必要があり/home/、のような一般的なものに置き換えることができないという欠点があり$1ます。

編集と比較する一般化のために(感謝@Michael)$VAR1缶使用

[ "${PWD:0:${#VAR}}" = $VAR ]

4
${#var}長さである$var、あなたのようにそれを一般化することができますので、[ "${PWD:0:${#1}}" = "$1" ]
マイケルMrozek

@Michael Mrozek♦:おかげで、完璧な:)に動作します
トビアスKienzler

2

私はあまりにもよく質問を理解していないが、親の見つけるために$ PWDを、行いますdirname $PWD。親の親を見つけるにはdirname $(dirname $PWD)、などを実行します...


これは、深さがわかっている場合にのみ機能し、そうでない場合はになり/ます。わかりました、再帰的にチェックできましたが、もっと簡単なものはありませんか?
トビアスキンツラー

1
@tobシェルプログラミングを知っていれば;-)
tshepang


0

うーん、条件[をテストするオプションがないのは残念ですSTRING1 starts with STRING2

を試すこともecho $PWD | grep '^$VAR'できますが、VAR特別な記号が含まれていると、興味深い方法で失敗する可能性があります。

awkindex関数はトリックを実行できるはずです。しかし、これはすべて、テストが非常に簡単なためには重すぎるようです。


[[ヨーヨーGET STARTSWITH [[$ PWD =〜^ \ /ホーム\ /]]ように、正規表現をして
teknopaul

0

パスの検索された部分が見つかった場合、変数を「空にする」:

[[ -z "${PWD//*\/home\/*/}" ]] && echo "toto"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.