เมื่อเขียนสคริปต์ทุบตีฉันจะหาเส้นทางที่แน่นอนของที่ตั้งของไฟล์ปัจจุบันได้อย่างไร


16

myBash.bashสมมติว่าฉันมีไฟล์ทุบตีที่เรียกว่า มันอยู่ใน:

/myDirect/myFolder/myBash.bash

ตอนนี้ฉันต้องการใช้สตริง/myDirect/myFolder(ตำแหน่งmyBash.bash) ภายในสคริปต์ มีคำสั่งที่ฉันสามารถใช้เพื่อค้นหาตำแหน่งนี้หรือไม่?

แก้ไข: แนวคิดคือฉันต้องการตั้งค่าโฟลเดอร์ zip ด้วยรหัสที่สามารถเริ่มต้นได้โดยสคริปต์ทุบตีในไฟล์ zip นั้น ฉันรู้เส้นทางไฟล์ที่เกี่ยวข้องของรหัสในไฟล์ zip นั้น แต่ไม่ใช่เส้นทางที่แน่นอนและฉันต้องการมัน วิธีหนึ่งคือการใส่รหัสในพา ธ หรือกำหนดเส้นทางของไฟล์เป็นตัวแปร อย่างไรก็ตามฉันจะค้นหาได้ง่ายขึ้นถ้าเป็นไปได้ที่ bash-file จะหาว่ามันอยู่ที่ไหนด้วยตัวมันเองแล้วสร้างเส้นทางที่เกี่ยวข้องไปยังไฟล์อื่นจากความรู้เกี่ยวกับโครงสร้างของไฟล์ zip


3
นี่อาจเหมาะกว่าสำหรับ stackoverflow ตรวจสอบคำถามเหล่านี้: stackoverflow.com/questions/4774054/... stackoverflow.com/questions/59895/...
Sethos II

1
ใช้อย่างไร โปรดอธิบาย
Sergiy Kolodyazhnyy

1
@SethosII คำถามนี้มีอยู่ในหัวข้อทั้งหมดที่นี่
Zanna

1
ฉันเพิ่มบริบทให้กับคำถาม ฉันคิดว่าอาจจะมีคำสั่งที่ง่าย / ชัดเจนในการรับเส้นทางไฟล์ของไฟล์ที่กำลังดำเนินการ แต่ดูเหมือนว่าคำตอบอย่างน้อยไม่ชัดเจน
dimpol

3
@ ซานาฉันไม่ได้พูดว่ามันเป็นเรื่องที่น่าสนใจฉันคิดว่ามันเหมาะสมกว่าและดังที่แสดงในลิงค์ที่ถามและตอบไปแล้วหลายครั้ง
Sethos II

คำตอบ:


24

คุณสามารถรับเส้นทางแบบเต็มเช่น:

realpath "$0"

และตามที่ Serg ชี้ให้เห็นคุณสามารถใช้dirnameเพื่อตัดชื่อไฟล์เช่นนี้

dirname "$(realpath $0)"

หรือดียิ่งขึ้นเพื่อป้องกันการอ้างอิงที่น่าอึดอัดใจและการแยกคำด้วยชื่อไฟล์ที่ยาก:

temp=$( realpath "$0"  ) && dirname "$temp"

ดีกว่าความคิดก่อนหน้าของฉันซึ่งจะแยกมัน (ฉันรู้ว่าจะมีวิธีที่ดีกว่า!)

realpath "$0" | sed 's|\(.*\)/.*|\1|'

หมายเหตุ

  • realpath ส่งคืนพา ธ ที่แท้จริงของไฟล์
  • $0 เป็นไฟล์นี้ (สคริปต์)
  • s|old|new|แทนที่oldด้วยnew
  • \(.*\)/บันทึกตัวละครใด ๆ ก่อน/สำหรับในภายหลัง
  • \1 ส่วนที่บันทึกไว้

2
+1 สำหรับการใช้งาน$0และsedเวทมนตร์ แต่sedเวทมนตร์ดังกล่าวไม่จำเป็นจริงๆเมื่อมีเครื่องมือเหมือนdirnameมีอยู่จริง
Sergiy Kolodyazhnyy

2
คุณมีคำตอบใช้แล้วrealpath: โดยrealpath "$( dirname $0 )"ส่วนตัวแล้วฉันจะใช้readlinkแต่นั่นคือฉัน:readlink -e $(dirname $0)
Sergiy Kolodyazhnyy

@Serg: จะไม่dirname "$(realpath "$0")"ดีกว่าเหรอ? โดยปกติหนึ่งต้องการทราบไดเรกทอรีหลักของไฟล์อ้างอิงแทนไดเรกทอรีแม่ของลิงค์สัญลักษณ์ที่อ้างถึงไฟล์ดังกล่าว
David Foerster

4
@Serg "$(dirname "$(realpath "$0")")"เป็นวิธีที่ตรงไปตรงมาที่สุด คำคมภายใน$()งานเป็นเรื่องปกติ
DepressedDaniel

@DepressedDaniel การค้นคว้าออนไลน์นิดหน่อยคุณพูดถูก: $()การเป็น subshell จะทำให้มีการเสนอราคาภายนอก ฉันจะไม่พูดว่ามันตรงไปตรงมาแม้ว่าจะไม่มีใครรู้ว่า$()เป็น subshells ทั้งหมด
Sergiy Kolodyazhnyy

5

หากสคริปต์อยู่ในเส้นทางของคุณคุณสามารถใช้สิ่งที่ชอบ

$ myloc=$(dirname "$(which foo.sh)")
$ echo "$myloc"
/path/to/foo.sh

แก้ไข: หลังจากอ่านความคิดเห็นจาก Serg นี่อาจเป็นโซลูชันทั่วไปที่ใช้งานได้ว่าสคริปต์อยู่ในเส้นทางของคุณหรือไม่

myloc==$(dirname "$(realpath $0)")
dirname "$myloc"

whichเหมาะสำหรับเมื่อสคริปต์อยู่ในหนึ่งในไดเรกทอรีที่เป็นส่วนหนึ่งของPATHตัวแปร ใช้$0จากภายในสคริปต์เช่นเดียวกับการแสดง Zanna แต่คำตอบของคุณนั้นถูกต้องเพราะคุณใช้dirnameแทนที่จะมายุ่งกับsedดังนั้น +1 สำหรับสิ่งนั้น
Sergiy Kolodyazhnyy

5

คำตอบที่ได้รับการยอมรับนั้นสมบูรณ์แบบ นี่เป็นอีกวิธีในการทำ:

cd "$(dirname "$0")"
/bin/pwd

/bin/pwdพิมพ์เส้นทางที่แท้จริงของไดเรกทอรีตรงข้ามกับpwdคำสั่ง builtin


0
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0}";;
  *) scriptdir="$wdir/${0#./}";;
esac
scriptdir="${scriptdir%/*}"
echo "$scriptdir"

มันถูกนำมาใช้เป็นข้อมูลอ้างอิงจากkenorbและAndro
ไม่มี dirname, readlink, realpath, BASH_SOURCE
ทั้งหมดเป็น builtins

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