Dapatkan jalur skrip saat ini ketika dijalankan melalui symlink


59

Saya memiliki utilitas yang terdiri dari beberapa direktori dengan beberapa skrip bash dan file pendukung yang akan digunakan untuk beberapa mesin di direktori yang berbeda di setiap mesin. Script harus dapat mereferensikan path relatif ke diri mereka sendiri jadi saya harus bisa mendapatkan path ke file yang saat ini sedang dieksekusi.

Saya menyadari dirname $0idiom yang bekerja dengan sempurna ketika skrip saya dipanggil langsung. Sayangnya ada keinginan untuk dapat membuat symlink ke skrip ini dari direktori yang sama sekali berbeda dan masih memiliki pekerjaan logika pathing relatif.

Contoh dari keseluruhan struktur driectory adalah sebagai berikut:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

Bagaimana saya dapat diandalkan referensi /usr/local/lib/foo/res/resource_file.txtdari script.shapakah itu dipanggil oleh /usr/local/lib/foo/bin/script.shatau ~mike/bin/link_to_script?

Jawaban:


80

Coba ini sebagai solusi tujuan umum:

DIR="$(cd "$(dirname "$0")" && pwd)"

Dalam kasus spesifik symlink berikut, Anda juga bisa melakukan ini:

DIR="$(dirname "$(readlink -f "$0")")"

Bekerja dengan sempurna dan jauh lebih sederhana daripada yang saya coba. Terima kasih!
Mike Deck

@MikeDeck Nikmati. Perhatikan bahwa saya memperbaiki beberapa masalah mengutip sejak posting pertama ... Anda mungkin menggunakan opsi dari edit terakhir jika Anda memiliki spasi atau karakter aneh lainnya di jalur Anda kapan-kapan. Bahkan jika itu tidak masalah untuk proyek ini, Anda dapat menyalin kode dari skrip Anda sendiri di jalan dan memiliki opsi terbaik yang penting!
Caleb

1
Saya harus mengklarifikasi, yang kedua bekerja dengan sempurna. Solusi pertama yang Anda berikan tidak berfungsi untuk symlink di sistem saya.
Mike Deck

4
@MikeDeck: Solusi pertama berfungsi untuk kasus tipikal memiliki berbagai direktori yang disinkronkan sebagai bagian dari path, tetapi tidak akan membantu jika biner terakhir adalah symlink. Itulah yang dikelola orang kedua.
Caleb

1
Tidak berfungsi jika file skrip adalah sourced (mis. $ source ./sript.sh) Ini berfungsi untuk kedua kasus:DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
FractalSpace

7

satu baris:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

2
Satu baris jawaban biasanya bukan yang paling bermanfaat. Silakan pertimbangkan memperluas jawaban Anda untuk memasukkan penjelasan, tautan, atau dokumentasi yang selanjutnya mendukung solusi yang Anda sarankan.
HalosGhost

1
sebenarnya, Anda tidak perlu melakukan ini, versi readlink dari jawaban asli berfungsi dengan baik jika tidak ada symlink yang terlibat sama sekali
PENULIS

3

readlink -f tidak bekerja untuk saya, saya memiliki kesalahan ini:

readlink: illegal option -- f
usage: readlink [-n] [file ...]

Tapi ini bekerja dengan baik:

DIR="$(dirname "$(readlink "$0")")"
echo $DIR

3
Maka Anda berada di Mac dan ini harus menjawab pertanyaan Anda .
Isaac

Ya, saya menggunakan MacOs @isaac, tapi saya tidak punya pertanyaan. Saya memposting perintah yang bekerja di sisi saya.
Kevin Campion

0

Satu tambahan kecil untuk skrip di atas. Opsi -P untuk pwd mengikuti symlink

DIR="$(cd "$(dirname "$0")" && pwd -P)"

7
Ini hanya berfungsi ketika symlink adalah bagian dari struktur direktori. Tidak berfungsi saat file itu sendiri ditautkan.
Oliver Gondža
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.