เหตุใด mkdir จึงล้มเหลว (ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว) ในสคริปต์ที่มี BIN_DIR =“ ~ / bin /”


10

เหตุใดคำสั่ง mkdir จึงล้มเหลวด้วย: "ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"?

#!/bin/bash

set -e

BIN_DIR="~/bin/"

if [ ! -d "$BIN_DIR" ]; then
  mkdir "$BIN_DIR"
fi

คำตอบ:


11

เกิดข้อผิดพลาดที่ผลิตเพราะตัวหนอน~จะยกมาตามที่อธิบายไว้ใน Zanna ของคำตอบ หากคุณต้องการใช้ส่วน~ที่เกี่ยวข้องของสคริปต์ควรเป็น:

BIN_DIR=~/bin/

หากด้วยเหตุผลใดก็ตามที่คุณต้องการอ้างอิงสตริงคุณสามารถใช้ตัวแปรสภาพแวดล้อม$HOME:

BIN_DIR="$HOME/bin/"

ในความคิดของฉันวิธีที่สองคือการปฏิบัติที่ดีกว่า


6
ไม่มีอะไรผิดปกติกับการใช้~สคริปต์ มันทำงานในลักษณะเดียวกับในบรรทัดคำสั่ง ปัญหาคือการที่บล็อกตัวหนอนขยายตัวข้อความที่อธิบายไว้ในคำตอบของ Zanna
terdon

@terdon ฉันเห็นด้วย แต่ฉันไม่ได้บอกว่ามีบางอย่างผิดปกติ แต่เป็นความคิดที่ดีกว่าเพราะคุณควรให้ความสนใจน้อยลง
pa4080

5
แต่ไม่มีความแตกต่างระหว่างบรรทัดคำสั่งและสคริปต์ที่นี่ ความจริงที่ว่าในสคริปต์ไม่เกี่ยวข้องอย่างสมบูรณ์คุณจะมีข้อผิดพลาดเดียวกันใน commandline ปัญหาคือข้อความไม่ได้อยู่ในสคริปต์
terdon

ในขณะที่จริงทั้งหมดก็ถูกต้องที่ใช้$HOMEในสคริปต์เป็นความคิดที่ดี
ของหวาน

3
@ pa4080 คุณสามารถเพิ่มคำอธิบายว่าทำไมคุณคิดว่าการขยายตัว$HOMEดีกว่าการใช้การขยายตัวหนอน คำอธิบายเดียวที่คุณให้คือพูดว่า "มันเป็นความคิดที่ดีกว่าเพราะคุณควรให้ความสนใจน้อยลง" ฉันไม่รู้ว่ามันหมายถึงอะไร คุณสามารถอธิบายมันในการแก้ไขได้ไหม? ถ้าไม่มีมันก็ไม่มีอะไรรองรับคำตอบของคุณดังนั้นแน่นอนว่ามันเป็นของมัน POSIX ต้องการการขยายตัวของ Tilde มาระยะหนึ่งแล้ว และบรรทัด hashbang ของสคริปต์คือ#!/bin/bashดังนั้นฉันจึงคิดว่าการพกพาไม่ใช่เหตุผล
Eliah Kagan

23

มันไม่ทำงานเพราะ~มีการเสนอราคา ราคาคู่ "ปราบขยายตัวหนอน ~/binมีไดเรกทอรีที่มีชื่ออักษรไม่เป็น ตามที่อธิบายไว้ในman bash(เหมืองที่เน้น):

Tilde Expansion

หากคำเริ่มต้นด้วยการunquotedตัวละครตัวหนอน ( `~ ') ทั้งหมดของตัวละครก่อนที่จะเฉือน unquoted แรก (หรือตัวละครที่ทุกคนถ้าไม่มีเฉือน unquoted) ถือว่าเป็นตัวหนอนคำนำหน้า หากไม่มีการอ้างถึงอักขระในเครื่องหมายคำนำหน้าตัวหนอนตัวอักษรในเครื่องหมายคำนำหน้าตัวหนอนหลังตัวหนอนจะถือว่าเป็นชื่อล็อกอินที่เป็นไปได้ หากชื่อล็อกอินนี้คือสตริง null ตัวหนอนจะถูกแทนที่ด้วยค่าของพารามิเตอร์เชลล์ HOME หาก HOME ไม่ได้ตั้งค่าโฮมไดเรกทอรีของผู้ใช้ที่ดำเนินการเชลล์จะถูกแทนที่แทน มิฉะนั้นคำนำหน้าตัวหนอนจะถูกแทนที่ด้วยไดเรกทอรีบ้านที่เกี่ยวข้องกับชื่อเข้าสู่ระบบที่ระบุ

คุณสามารถลบเครื่องหมายคำพูดได้เนื่องจาก~เป็นอักขระตัวเดียวในพา ธ~/binที่จะทำให้เชลล์ทำการขยายตัวและเราต้องการการขยายในกรณีนี้ เชลล์จะไม่ทำการขยายเพิ่มเติมใด ๆ จากผลลัพธ์ของการขยายตัวของตัวหนอนอย่างน้อยใน Bash 4ซึ่งมี Ubuntu รุ่นปัจจุบันหรือจากระยะไกลทั้งหมด ดังนั้นแม้ว่าโฮมไดเร็กตอรี่ของคุณจะมีตัวอักษรผิดปกติเช่นช่องว่าง, มันก็โอเค

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


ตามคำสั่งนี้"การขยายตัวพารามิเตอร์ไม่ได้ปราบปรามโดยราคาคู่โดยเฉพาะราคาเดียว" : การส่งออกของมีcd '~' -bash: cd: ~: No such file or directory
pa4080

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