Dapatkan jalur direktori file dari jalur file


400

Di Bash, jika VAR="/home/me/mydir/file.c", bagaimana saya dapatkan "/home/me/mydir"?

Jawaban:


649

dirnamedan basenameapakah alat yang Anda cari untuk mengekstraksi komponen jalur:

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

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

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

$ basename "${VAR}"
file.c

Itu bukan perintah Bash internal tetapi itu adalah bagian dari standar POSIX (lihat dirname, basename) dan karenanya harus tersedia pada sebagian besar sistem yang akan menjalankan Bash.


4
Mengapa menggunakan tanda kurung di sekitar nama variabel, dan bukan "$ VAR" misalnya?
user658182

1
stackoverflow.com/questions/8748831/… menjawab pertanyaan di atas.
user658182

1
@ user658182 Dalam contoh khusus ini, ini dilakukan karena kebiasaan, bukan keharusan.
Abandoned Cart

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

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

Untuk menghindari ketergantungan dengan basenamedandirname


3
Karena keduanya adalah bagian dari POSIX, ketergantungan seharusnya tidak menjadi masalah.
orkoden

1
orkoden, kamu benar. Tujuan dari jawaban saya adalah untuk menunjukkan bahwa tidak ada kewajiban untuk melakukan dua proses tambahan. bash cukup mandiri untuk use case.
Emmanuel Devaux

2
Saya menggunakan metode Emmanuel karena saya ingin memberikan file atau nama folder, dan kemudian menghitung jalur folder. Menggunakan regex ini melakukan hal yang benar, sedangkan fungsi dirname mengembalikan folder induk ketika saya memasukkan folder.
AnneTheAgile

8
Namun, jika tidak ada info jalur dalam $ VAR, $ {VAR% / *} / test menghasilkan nilai tak terduga sama dengan $ VAR / test sedangkan $ (dirname $ VAR) akan menghasilkan nilai ./test yang lebih mudah diprediksi dan sesuai. Ini adalah masalah besar karena yang pertama akan mencoba untuk memperlakukan nama file sebagai direktori sedangkan yang kedua akan baik-baik saja.
davemyron

19

Pada catatan terkait, jika Anda hanya memiliki nama file atau jalur relatif, dirnamedengan sendirinya tidak akan membantu. Bagi saya, jawabannya akhirnya readlink.

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

Anda kemudian dapat menggabungkan keduanya untuk mendapatkan hanya direktori.

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

1
jika lebih dari satu komponen jalur tidak ada, Anda harus menggunakan readlink -m "$fname"untuk
mengkanonikkan

7

Jika Anda peduli file target menjadi tautan simbolis, pertama Anda dapat memeriksanya dan mendapatkan file aslinya. Klausa if di bawah ini dapat membantu Anda.

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

5

Saya sedang bermain dengan ini dan datang dengan alternatif.

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

$ DIR=`echo $VAR |xargs dirname`

$ echo $DIR
/home/me/mydir

Bagian yang saya suka adalah mudah untuk memperpanjang cadangan pohon:

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

$ echo $DIR
/home

1

Berikut ini adalah skrip yang saya gunakan untuk pemangkasan rekursif. Ganti $ 1 dengan direktori yang Anda inginkan, tentu saja.

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

Pertama, saya telah mengganti /dengan ruang kosong ( ). Lalu, saya menghapus semua karakter sebelum ada ruang kosong ( ). Pada akhirnya, saya menghapus karakter pertama yaitu spasi kosong ( ).

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

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

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

di mana Anda mendapatkan path lengkap dengan new_path = $(dirname ${BASH_SOURCE[0]}). Anda mengubah direktori saat ini dengan cd new_path dan kemudian menjalankan pwduntuk mendapatkan path lengkap ke direktori saat ini.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.