วิธีตรวจสอบว่า $ PWD เป็นไดเรกทอรีย่อยของเส้นทางที่กำหนดหรือไม่


25

เช่นตรวจสอบว่า$PWDเป็นไดเรกทอรีย่อยของ / home ในคำอื่น ๆ ที่ฉันกำลังค้นหาการดำเนินการสตริงทุบตีเพื่อตรวจสอบว่าหนึ่งสตริงเริ่มต้นด้วยอีก

คำตอบ:


26

หากคุณต้องการทดสอบอย่างน่าเชื่อถือว่าไดเรกทอรีนั้นเป็นไดเรกทอรีย่อยของไดเรกทอรีอื่นหรือไม่คุณจะต้องมีมากกว่าการตรวจสอบคำนำหน้าสตริง คำตอบของ Gilles อธิบายโดยละเอียดเกี่ยวกับวิธีการทดสอบนี้อย่างถูกต้อง

แต่ถ้าคุณต้องการตรวจสอบคำนำหน้าสตริงอย่างง่าย (บางทีคุณอาจทำให้เส้นทางของคุณเป็นปกติ?) นี่เป็นวิธีที่ดี:

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

หาก$PWDเริ่มต้นด้วย "/ home /" มันจะถูกถอดออกทางด้านซ้ายซึ่งหมายความว่ามันจะไม่ตรงกับด้านขวาดังนั้น "! =" จะส่งกลับค่าจริง


1
+1 สมบูรณ์แบบและสำหรับกรณีทั่วไปมากขึ้น: [ "${PWD##$VAR}" != "$PWD" ]และถ้านี่เป็น [code-golf] ( stackoverflow.com/questions/tagged/code-golf) คำถามคุณจะต้องเอาชนะฉันด้วยตัวอักษรสองตัว ;-) นอกจากนี้ยังมีลักษณะ อ่านได้มากขึ้น ...
Tobias Kienzler

FWIW สิ่งนี้อาจมีประโยชน์ด้วย:${PWD/#$HOME/\~}
user1338062

ก็ได้ แต่วิธีการเกี่ยวกับ PWD = "/ home /../ ฯลฯ /"
Alexis Peters

1
@AlexisPeters: คุณพูดถูก: ฉันกำลังมุ่งเน้นไปที่ส่วน "คำนำหน้าสตริง" ของคำถามและฉันได้แก้ไขให้ชัดเจนยิ่งขึ้น Gilles ได้ครอบคลุมวิธีที่เหมาะสมในการตรวจสอบไดเรกทอรีย่อย
Jander

1
ใช้"${PWD%%/subdir*}"เพื่อตรวจสอบว่าผู้ใช้อยู่ในsubdirหรืออยู่ในไดเรกทอรีย่อยsubdirเนื่องจาก %% จับจากจุดสิ้นสุดของสตริงแทนการเริ่มต้น สิ่งนี้จะเป็นประโยชน์สำหรับทุกคนที่กำลังมองหาข้อมูลเพิ่มเติมเกี่ยวกับการทดแทนพารามิเตอร์: tldp.org/LDP/abs/html/parameter-substitution.html
George Pantazes

33

ในการทดสอบว่าสตริงนั้นเป็นคำนำหน้าของสตริงอื่นในเชลล์สไตล์ใดก็ตาม

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

หลักการเดียวกันนี้ใช้สำหรับการทดสอบส่วนต่อท้ายหรือซับสตริง โปรดสังเกตว่าในcaseโครงสร้างเหมือนชื่อไฟล์*ตรงกับตัวอักษรใด ๆ รวมถึงหรือเริ่มต้น/.

ในเชลล์ที่ใช้[[ … ]]ไวยากรณ์ (เช่น 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 ขอบคุณสำหรับคำตอบที่ครบถ้วนสมบูรณ์ ฉันไม่ได้พิจารณาการเชื่อมโยงและลักษณะระบบแฟ้มเมื่อถามนี้ แต่มันเป็นเรื่องดีที่จะรู้แน่นอน
โทเบียส KIENZLER

8

รุ่นน้ำมันดิบ:

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

มีข้อเสียที่หนึ่งที่มีการนับตัวอักษรแรกและหนึ่งไม่สามารถแทนที่โดยสิ่งที่ทั่วไปเช่น/home/$1

แก้ไข (ขอบคุณ @Michael) เพื่อให้การเปรียบเทียบทั่วไป$VARสามารถใช้งานได้

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

4
${#var}คือความยาว$varดังนั้นคุณสามารถพูดคุยทั่วไปได้[ "${PWD:0:${#1}}" = "$1" ]
Michael Mrozek

@Michael Mrozek ♦: ขอบคุณทำงาน :) ที่สมบูรณ์แบบ
โทเบียส KIENZLER

2

ฉันไม่เข้าใจคำถามที่ดีเกินไป แต่จะหาแม่ของ$ PWDdirname $PWDทำ หากต้องการค้นหาพาเรนต์ของพาเรนต์ให้รันdirname $(dirname $PWD)และต่อไป ...


/ที่จะทำงานเฉพาะในกรณีที่ผมรู้ว่าลึกมิฉะนั้นผมจะจบลงด้วย ตกลงฉันสามารถตรวจสอบซ้ำ แต่ไม่มีอะไรที่ง่ายกว่านี้หรือ
Tobias Kienzler

1
@tob ถ้าเพียง แต่ผมรู้ว่าการเขียนโปรแกรมเปลือก ;-)
tshepang

1

การใช้awk:

echo $PWD | awk -v h="/home" '$0 ~ h {print "MATCH"}'

+1 สำหรับการทำงาน แต่ช้ากว่าการทดสอบทุบตีเล็กน้อย
Tobias Kienzler

0

อืมมันน่าเสียดายที่[ไม่มีตัวเลือกของSTRING1 starts with STRING2เงื่อนไขการทดสอบ

คุณอาจลองecho $PWD | grep '^$VAR'แต่อาจล้มเหลวในรูปแบบที่น่าสนใจเมื่อVARมีสัญลักษณ์พิเศษ

awkของindexฟังก์ชั่นควรจะสามารถทำเคล็ดลับ แต่ทั้งหมดนี้ดูเหมือนจะหนักเกินไปสำหรับสิ่งที่ง่ายต่อการทดสอบ


[[ไม่ regexp ดังนั้นคุณจะได้รับ startswith [[$ PWD = ~ ^ \ / home \ /]]
teknopaul

0

หากพบส่วนของเส้นทางที่พบฉัน "ว่าง" ตัวแปร:

[[ -z "${PWD//*\/home\/*/}" ]] && echo "toto"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.