ตรวจสอบว่ามีไดเรกทอรีอยู่โดยใช้อักขระหน้าแรก (~) ใน bash ล้มเหลวหรือไม่


16

เหตุใดจึงbashตรวจสอบต่อไปนี้หากไดเรกทอรีล้มเหลว

if [ ! -d "~/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

~/Desktopมีอยู่จริง นี่คือบน Mac โดยวิธีการ


ปัญหาเกิดขึ้นกับสคริปต์ประเภทนี้

read -p "Provide the destination directory: " DESTINATION

if [ ! -d $DESTINATION ]; then
    echo "\t'$DESTINATION' does not exist." >&2;
    exit 1;
fi

1
เช่นเดียวกับเมื่อคุณทำcd "~/Desktop"คุณได้รับข้อผิดพลาด มันจะต้องไม่มีการอ้างอิงหรือเก็บไว้เป็นตัวแปร (ไม่มีเครื่องหมายคำพูด) ตัวอย่างเช่นใช้a=~/Desktop; cd $a;งานได้ แต่ไม่a="~/Desktop"; cd Desktop;เห็นserverfault.com/questions/417252/…
dylnmc

คำตอบ:


7

จัสตินชี้แจงคำถามของเขาในความคิดเห็นแรกเกี่ยวกับคำตอบของควอนตั้ม เขากำลังอ่านข้อความเป็นบรรทัดโดยใช้read(หรือโดยวิธีการไดนามิกอื่น ๆ ) และต้องการขยายตัวหนอน

คำถามจะกลายเป็น "คุณจะดำเนินการขยายตัวหนอนบนเนื้อหาของตัวแปรได้อย่างไร"

วิธีการทั่วไปคือการใช้evalแต่มันมาพร้อมกับ caveats ที่สำคัญบางอย่างคือช่องว่างและการเปลี่ยนเส้นทางออก ( >) ในตัวแปร ดูเหมือนว่าต่อไปนี้จะได้ผลสำหรับฉัน:

read -p "Provide the destination directory: " DESTINATION

if [ ! -d "`eval echo ${DESTINATION//>}`" ]; then
    echo "'$DESTINATION' does not exist." >&2;
    exit 1;
fi

ลองใช้กับอินพุตต่อไปนี้:

~
~/existing_dir
~/existing dir with spaces
~/nonexistant_dir
~/nonexistant dir with spaces
~/string containing > redirection
~/string containing > redirection > again and >> again

คำอธิบาย

  • ${mypath//>}แถบออกตัวละครที่สามารถบังคับไฟล์ระหว่าง >eval
  • นี่eval echo ...คือสิ่งที่ทำให้เกิดการขยายตัวตัวหนอนที่แท้จริง
  • เครื่องหมายคำพูดคู่รอบ ๆevalมีไว้เพื่อรองรับชื่อไฟล์ที่มีช่องว่าง

เป็นส่วนเสริมสำหรับสิ่งนี้คุณสามารถปรับปรุง UX โดยการเพิ่ม-eตัวเลือกในการอ่าน:

read -p "Provide the destination directory: " -e DESTINATION

ตอนนี้เมื่อผู้ใช้พิมพ์ในแท็บตัวหนอนและฮิตมันจะขยายตัว วิธีการนี้ไม่ได้แทนที่วิธีการประเมินผลข้างต้นอย่างไรก็ตามเนื่องจากการขยายจะเกิดขึ้นเฉพาะเมื่อผู้ใช้เยี่ยมชมแท็บ หากเขาเพียงพิมพ์ ~ / foo และกดปุ่ม Enter ก็จะยังคงเป็นตัวหนอน

ดูสิ่งนี้ด้วย:


23

ลบเครื่องหมายคำพูดคู่รอบไดเรกทอรีเพื่อดูว่าทำงานได้หรือไม่:

if [ ! -d ~/Desktop ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

สาเหตุของการขยายตัวของตัวหนอนจะใช้งานได้เมื่อไม่มีการอ้างอิง

info "(bash) Tilde Expansion"

3.5.2 Tilde Expansion
---------------------

If a word begins with an unquoted tilde character (`~'), all of the
characters up to the first unquoted slash (or all characters, if there
is no unquoted slash) are considered a TILDE-PREFIX.  If none of the
characters in the tilde-prefix are quoted, the characters in the
tilde-prefix following the tilde are treated as a possible LOGIN NAME.
If this login name is the null string, the tilde is replaced with the
value of the `HOME' shell variable.  If `HOME' is unset, the home
directory of the user executing the shell is substituted instead.
Otherwise, the tilde-prefix is replaced with the home directory
associated with the specified login name.

ถ้าค่านั้นมาเป็นแบบไดนามิก คือ ( pastie.org/4471350 ) และเป็นDESTINATION ~/Desktop
จัสติน

3
การขยายตัวของ Tilde นั้นเกิดขึ้นเมื่อตัวแปรถูกตั้งค่าไม่ใช่เมื่อประเมินผลดังนั้นจึงไม่ใช่ตัวอย่างที่ดี
MadHatter

+1 นี่เพียงพอที่จะแก้ปัญหาของฉัน
Flying Fisher

4

ไม่เพียงทำงานบน Mac เท่านั้น แต่ยังใช้งานได้กับทุกแพลตฟอร์ม

เมื่อคุณพูดว่า "~ / Desktop" คุณกำลังบอกให้ทุบตีเพื่อค้นหา Desktop ภายในโฟลเดอร์ ~ คำพูดจะลบวัตถุประสงค์พิเศษของ ~

ดู - http://www.gnu.org/software/bash/manual/bashref.html#Tilde-Expansion

ลบเครื่องหมายคำพูดคู่และควรจะได้ผล


1

วิ่ง

echo $HOME

ใช้$HOMEและตรวจสอบให้แน่ใจว่าผู้ใช้กำลังใช้งานสคริปต์จริงๆ ถ้ารากใช้~ของมันจะไปดูในไม่/root/home/$USER

if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

-1
if [ ! -d "$HOME/Desktop" ]; then
   echo "DOES NOT EXIST"
   exit 1;
fi

ควรเป็น $ HOME แทนที่จะเป็น ~

~ คือสิ่งที่แป้นพิมพ์


หากคุณอ่านคำตอบอื่นที่นี่คุณจะรู้ว่านี่เป็นสิ่งที่ผิด
ลูกไก่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.