$ PWD'nin verilen bir yolun alt dizini olup olmadığı nasıl kontrol edilir?


25

Örneğin $PWD, / home alt dizini olup olmadığını kontrol edin . Başka bir deyişle, bir dize diğeriyle başlayıp başlamadığını kontrol etmek için bir bash string işlemi arıyorum.

Yanıtlar:


26

Bir dizinin bir başkasının alt dizini olup olmadığını güvenilir bir şekilde test etmek istiyorsanız, bir dize öneki kontrolünden daha fazlasına ihtiyacınız olacaktır. Gilles'un cevabı bu testin nasıl yapıldığını ayrıntılı olarak açıklar.

Ancak basit bir dize önek kontrolü yapmak istiyorsanız (belki de yollarınızı normalleştirdiniz mi?), Bu iyi bir durum:

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

Eğer $PWD"/ home /" ile başlar, bunun "! =" True değerini döndürür, böylece sağ tarafını maç anlamına gelir sol tarafında, içinde sıyrılıp alır.


1
+1 mükemmel, ve daha genel bir durum için: [ "${PWD##$VAR}" != "$PWD" ]Ve eğer bu bir [code-golf] olsaydı ( stackoverflow.com/questions/tagged/code-golf)question beni iki karakterle yenin ;-) daha okunabilir ...
Tobias Kienzler

FWIW, bu da faydalı olabilir:${PWD/#$HOME/\~}
user1338062

Tamam, pwd = "/ home /../ etc /"
Alexis Peters

1
@AlexisPeters: Haklısın: Sorunun "string prefix" kısmına odaklanıyordum ve bunu daha net hale getirmek için düzenleme yaptım. Gilles, alt dizinleri kontrol etmenin uygun yolunu güzel bir şekilde ele almıştır.
Jander,

1
"${PWD%%/subdir*}"Kullanıcının şu anda subdirbir alt dizininde mi yoksa alt dizininde mi olduğunu tespit etmek için kullanın subdir, çünkü %% başlangıç ​​yerine dizenin sonundan yakalanır. Bu, parametre değişimi hakkında daha fazla bilgi edinmek isteyen herkes için yararlı olmalıdır: tldp.org/LDP/abs/html/parameter-substitution.html
George Pantazes

33

Bir dizenin bir Bourne tarzı kabuğunda bir başkasının öneki olup olmadığını test etmek için:

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

Aynı prensip bir son ek veya alt dize testi için de geçerlidir. İçinde olduğunu unutmayın caseyapılara, dosya adlarında aksine *bir de dahil olmak üzere herhangi bir karakterle, kibrit /veya bir başlangıç ..

[[ … ]]Sözdizimini uygulayan kabuklarda (yani bash, ksh ve zsh), bir dizgiyi bir kalıpla eşleştirmek için kullanılabilir. ( [Komutun yalnızca dizeleri eşitlik için test edebileceğini unutmayın .)

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

Geçerli dizinin altında olup olmadığını özellikle test ediyorsanız /home, sembolik bağlar nedeniyle basit bir alt dize testi yeterli değildir.

/homeKendi başına bir dosya sistemi varsa , geçerli dizinin ( .) o dosya sisteminde olup olmadığını sınayın .

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

NetBSD, OpenBSD veya GNU'ya (örneğin Linux) readlinksahipseniz, readlink -fsembolik bağlantıları bir yoldan şeritlemek için kullanabilirsiniz .

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

Aksi takdirde, pwdgeçerli dizini göstermek için kullanabilirsiniz . Ancak, kabuğunuz cdkomutları izliyorsa ve dizine ulaşmak için kullandığınız adı “gerçek” konum yerine saklıyorsa, yerleşik bir kabuk kullanmamaya dikkat etmelisiniz .

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

+1 Bu ayrıntılı cevap için teşekkürler. Bunu sorarken linkleri ve dosya sistemi özelliklerini düşünmedim, ama kesinlikle bilmek güzel
Tobias Kienzler

8

Ham versiyon:

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

Dezavantajı var ki, önce karakterleri saymak zorunda, biri de /home/genel bir şeyle yerini alamaz $1.

edit (thanks @Michael) ile genelleme yapmak için karşılaştırma $VARyapabilir

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

4
${#var}uzunluğu nedir $var, yani genelleştirebilirsiniz[ "${PWD:0:${#1}}" = "$1" ]
Michael Mrozek

@Michael Mrozek Thanks: Teşekkürler, mükemmel çalışıyor :)
Tobias Kienzler

2

Seni çok iyi soruyu anlamadım, ama üst öğesini bulmak için $ PWD , do dirname $PWD. Ebeveynin ebeveyni bulmak için koş dirname $(dirname $PWD)ve benzeri ...


Bu sadece derinliği bilsem işe yarayacaktı, yoksa sonunda bitirdim /. Tamam, özyinelemeli kontrol edebilirim ama daha kolay bir şey yok mu?
Tobias Kienzler

1
@tob Keşke kabuk programlamayı bilseydim ;-)
tshepang


0

Hm, [sınama STRING1 starts with STRING2koşulu seçeneği olmayan yazık .

Deneyebilirsiniz echo $PWD | grep '^$VAR', ancak VARözel semboller içerdiğinde ilginç şekillerde başarısız olabilir .

awk'nin indexişlevi hile yapabilmeli. Fakat bütün bunlar test etmek için bu kadar kolay bir şey için çok ağır görünüyor.


[[Yo olsun startswith [[$ PWD = ~ ^ \ / home \ /]] böylece Regexp'i yapar
teknopaul

0

Yolun aranan kısmı bulunursa değişkeni "boşaltırım":

[[ -z "${PWD//*\/home\/*/}" ]] && echo "toto"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.