รับเส้นทางไดเรกทอรีไฟล์จากเส้นทางไฟล์


คำตอบ:


648

dirnameและbasenameเป็นเครื่องมือที่คุณกำลังมองหาสำหรับการแยกส่วนประกอบของเส้นทาง:

$ VAR=/home/me/mydir/file.c

$ DIR=$(dirname "${VAR}")

$ echo "${DIR}"
/home/me/mydir

$ basename "${VAR}"
file.c

พวกเขาไม่ได้ภายในคำสั่งทุบตี แต่พวกเขาเป็นส่วนหนึ่งกำลังของมาตรฐาน POSIX (ดูdirname, basename) และดังนั้นควรจะมีอยู่ในส่วนใหญ่ของระบบที่จะทำงานทุบตี


4
ทำไมการใช้วงเล็บรอบชื่อตัวแปรและไม่ใช่ "$ VAR" เป็นตัวอย่าง?
user658182

1
stackoverflow.com/questions/8748831/…ตอบคำถามข้างต้น
user658182

1
@ user658182 ในตัวอย่างนี้มันทำมาจากนิสัยไม่จำเป็น
รถเข็นที่ถูกทิ้งร้าง

95
$ export VAR=/home/me/mydir/file.c
$ export DIR=${VAR%/*}
$ echo "${DIR}"
/home/me/mydir

$ echo "${VAR##*/}"
file.c

เพื่อหลีกเลี่ยงการพึ่งพากับbasenameและdirname


3
เนื่องจากทั้งคู่เป็นส่วนหนึ่งของ POSIX การขึ้นต่อกันจึงไม่ควรเป็นปัญหา
orkoden

1
หรือโคเด็นคุณพูดถูก เป้าหมายของคำตอบของฉันคือแสดงให้เห็นว่าไม่มีข้อผูกมัดในการดำเนินการเพิ่มเติมสองกระบวนการ bash นั้นเพียงพอสำหรับกรณีการใช้งาน
Emmanuel Devaux

2
ฉันใช้วิธีของ Emmanuel เพราะฉันต้องการส่งไฟล์หรือชื่อโฟลเดอร์แล้วคำนวณเส้นทางโฟลเดอร์ การใช้ regex นี้ทำสิ่งที่ถูกต้องในขณะที่ฟังก์ชั่น dirname ส่งคืนโฟลเดอร์หลักเมื่อฉันป้อนโฟลเดอร์
AnneTheAgile

8
อย่างไรก็ตามหากไม่มีข้อมูลเส้นทางใน $ VAR, $ {VAR% / *} / test จะสร้างค่าที่ไม่คาดคิดเท่ากับ $ VAR / ทดสอบในขณะที่ $ (dirname $ VAR) จะให้ค่าที่คาดการณ์และเหมาะสมมากขึ้นของ. / test นี่เป็นเรื่องใหญ่เพราะอดีตจะพยายามที่จะรักษาชื่อไฟล์เป็นไดเรกทอรีในขณะที่หลังจะตกลง
davemyron

19

ในบันทึกที่เกี่ยวข้องหากคุณมีชื่อไฟล์หรือเส้นทางสัมพัทธ์dirnameด้วยตัวมันเองจะไม่ช่วย readlinkสำหรับผมคำตอบที่จบลงด้วยการ

fname='txtfile'    
echo $(dirname "$fname")                # output: .
echo $(readlink -f "$fname")            # output: /home/me/work/txtfile

จากนั้นคุณสามารถรวมทั้งสองอย่างเพื่อให้ได้ไดเรกทอรีเท่านั้น

echo $(dirname $(readlink -f "$fname")) # output: /home/me/work

1
หากไม่มีส่วนประกอบของพา ธ มากกว่าหนึ่งคุณควรใช้readlink -m "$fname"เพื่อกำหนดชื่อที่กำหนดแบบเรียกซ้ำ
EDkan

7

หากคุณสนใจไฟล์เป้าหมายที่จะเป็นลิงค์สัญลักษณ์อันดับแรกคุณสามารถตรวจสอบและรับไฟล์ต้นฉบับได้ ประโยคถ้าด้านล่างอาจช่วยคุณได้

if [ -h $file ]
then
 base=$(dirname $(readlink $file))
else
 base=$(dirname $file)
fi

5

ฉันเล่นกับสิ่งนี้และหาทางเลือกอื่น

$ VAR=/home/me/mydir/file.c

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

ส่วนที่ฉันชอบคือมันง่ายต่อการขยายการสำรองข้อมูลต้นไม้:

$ DIR=`echo $VAR |xargs dirname |xargs dirname |xargs dirname`

$ echo $DIR
/home

1

นี่คือสคริปต์ที่ฉันใช้สำหรับการตัดทอนซ้ำ แทนที่ $ 1 ด้วยไดเรกทอรีที่คุณต้องการแน่นอน

BASEDIR="$1"
IFS=$'\n'
cd $BASEDIR
 for f in $(find . -type f -name ' *')
 do 
    DIR=$(dirname "$f")
    DIR=${DIR:1}
    cd $BASEDIR$DIR
    rename 's/^ *//' *
 done

0

ก่อนอื่นฉันแทนที่/ด้วยช่องว่าง ( ) จากนั้นฉันลบอักขระทั้งหมดก่อนช่องว่าง ( ) ในตอนท้ายฉันลบอักขระตัวแรกที่มีที่ว่าง ( )

$ VAR="/home/me/mydir/file.c"

$ echo $VAR | tr '/' ' ' | sed 's/^.* / /' | cut -c2-
file.c

0
HERE=$(cd $(dirname $BASH_SOURCE) && pwd)

ที่คุณได้รับเส้นทางที่เต็มไปด้วยnew_path$(dirname ${BASH_SOURCE[0]}) = คุณเปลี่ยนไดเรกทอรีปัจจุบันด้วยcd new_pathแล้วเรียกใช้pwdเพื่อรับเส้นทางแบบเต็มไปยังไดเรกทอรีปัจจุบัน

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