Saya mencoba untuk mendapatkan jalur absolut ke skrip yang sedang berjalan di OS X.
Saya melihat banyak balasan datang readlink -f $0
. Namun karena OS X readlink
sama dengan BSD, itu tidak berfungsi (bekerja dengan versi GNU).
Apakah ada solusi out-of-the-box untuk ini?
$( cd "$(dirname "$0")" ; pwd -P )
Jawaban:
Ada
realpath()
fungsi C yang akan melakukan pekerjaan itu, tapi saya tidak melihat apa pun yang tersedia di baris perintah. Ini pengganti yang cepat dan kotor:Ini mencetak jalan secara verbatim jika dimulai dengan a
/
. Jika tidak, itu harus berupa jalur relatif, jadi itu tergantung$PWD
ke depan. The#./
bagian strip off./
dari depan$1
.sumber
realpath ../something
kembali$PWD/../something
command -v realpath >/dev/null 2>&1 || realpath() { ... }
Tiga langkah sederhana ini akan menyelesaikan ini dan banyak masalah OS X lainnya:
brew install coreutils
grealpath .
(3) dapat diubah menjadi hanya
realpath
, lihat (2) keluaransumber
$( cd "$(dirname "$0")" ; pwd -P )
berfungsi dengan baik untuk saya.XXX
dan beberapa orangcd xxx
kemudianpwd
akan kembali.../xxx
. Kecuali untuk jawaban ini, semua solusi di atas akan munculxxx
ketika Anda benar-benar menginginkannyaXXX
. Terima kasih!realpath
, lalu apa yang terjadi ketika Anda hampir pasti akan membutuhkan barang lain daricoreutils
? Tulis ulang fungsi-fungsi itu di bash juga? : PUgh. Saya menemukan jawaban sebelumnya agak kurang karena beberapa alasan: khususnya, jawaban tersebut tidak menyelesaikan beberapa tingkat tautan simbolis, dan mereka sangat "Bash-y". Meskipun pertanyaan awal secara eksplisit meminta "skrip Bash", pertanyaan tersebut juga menyebutkan tentang Mac OS X BSD-like, non-GNU
readlink
. Jadi, inilah upaya pada beberapa portabilitas yang masuk akal (saya telah memeriksanya dengan bash sebagai 'sh' dan tanda hubung), menyelesaikan sejumlah tautan simbolik; dan itu juga harus bekerja dengan spasi di jalur, meskipun saya tidak yakin perilakunya jika ada spasi putih nama dasar utilitas itu sendiri, jadi mungkin, um, hindari itu?Harapan itu bisa berguna bagi seseorang.
sumber
local
variabel yang didefinisikan di dalam fungsi agar tidak mencemari namespace global. Mislocal OURPWD=...
. Bekerja setidaknya untuk pesta.BASENAME=$(basename "$LINK")
inside the while dan menggunakannya di penyetel LINK kedua dan penyetel..
referensi induk dengan cara yangrealpath
sama. Dengan homebrewcoreutils
terinstal, cobaln -s /var/log /tmp/linkexample
kemudianrealpath /tmp/linkexample/../
; cetakan ini/private/var
. Tetapi fungsi Anda menghasilkan/tmp/linkexample/..
sebaliknya, karena..
bukan symlink.Varian yang lebih ramah baris perintah dari solusi Python:
sumber
python -c "import os; import sys; print(os.path.realpath(sys.argv[1]))"
Saya sedang mencari solusi untuk digunakan dalam skrip penyediaan sistem, yaitu, dijalankan bahkan sebelum Homebrew diinstal. Kurangnya solusi yang tepat, saya baru saja memindahkan tugas ke bahasa lintas platform, misalnya, Perl:
Lebih sering yang sebenarnya kita inginkan adalah direktori yang berisi:
sumber
FULLPATH=$(perl -e "use Cwd 'abs_path'; print abs_path('$0')")
. Ada alasan melawan?''
tidak anti peluru. Ini rusak jika$0
berisi satu kutipan, misalnya. Contoh yang sangat sederhana: coba versi Anda di/tmp/'/test.sh
, dan panggil/tmp/'/test.sh
dengan jalur lengkapnya./tmp/'.sh
,.Karena ada realpath yang lain memiliki keluar menunjuk:
Makefile:
Kemudian kompilasi dengan
make
dan masukkan tautan lunak dengan:ln -s $(pwd)/realpath /usr/local/bin/realpath
sumber
gcc realpath.c -o /usr/local/bin/realpath
?/usr/local/bin
Gunakan Python untuk mendapatkannya:
sumber
dirname
akan memberikan nama direktori/path/to/file
, yaitu/path/to
.cd /path/to; pwd
memastikan bahwa jalurnya mutlak.basename
akan memberikan nama file saja/path/to/file
, yaitufile
.sumber
Jadi seperti yang Anda lihat di atas, saya memotretnya sekitar 6 bulan yang lalu. Saya benar-benar melupakannya sampai saya menemukan diri saya membutuhkan hal yang sama lagi. Saya benar - benar terkejut melihat betapa belum sempurnanya itu; Saya telah mengajar diri saya sendiri untuk membuat kode cukup intensif selama sekitar satu tahun sekarang, tetapi saya sering merasa mungkin saya belum belajar apa pun sama sekali ketika hal-hal yang paling buruk.
Saya akan menghapus 'solusi' di atas, tetapi saya sangat menyukainya sebagai catatan tentang seberapa banyak yang telah saya pelajari selama beberapa bulan terakhir.
Tapi saya ngelantur. Saya duduk dan mengerjakan semuanya tadi malam. Penjelasan di komentar seharusnya cukup. Jika Anda ingin melacak salinan yang sedang saya kerjakan, Anda dapat mengikuti intinya. Ini mungkin melakukan apa yang Anda butuhkan.
sumber
..
referensi induk; misalnya/foo/link_to_other_directory/..
diselesaikan sebagai/foo
bukan induk dari jalur apa pun yang/foo/link_to_other_directory
ditunjuk oleh symlink .readlink -f
danrealpath
menyelesaikan setiap komponen jalur mulai dari akar dan memperbarui target tautan sebelumnya ke sisa yang masih diproses. Saya telah menambahkan jawaban untuk pertanyaan ini dengan menerapkan ulang logika itu.realpath untuk Mac OS X
Contoh dengan jalur terkait:
Contoh dengan folder home
sumber
..
itu tidak menghasilkan jawaban yang benar, jadi saya menambahkan tanda centang apakah jalur yang diberikan adalah direktori:if test -d $path ; then echo $(cd "$path"; pwd) ; else [...]
"$(dirname $(dirname $(realpath $0)))"
berhasil, jadi butuh sesuatu yang lain ...echo
juga tidak boleh dilakukan...
referensi induk sebelum menyelesaikan symlink, bukan setelah; coba ini dengan homebrewcoreutils
terinstal, buat tautan denganln -s /var/log /tmp/linkexample
lalu jalankanrealpath /tmp/linkexample/../
; cetakan ini/private/var
. Tetapi fungsi Anda menghasilkan/tmp/linkexample/..
sebaliknya, karenapwd
masih muncul/tmp/linkexample
setelah cd.Di macOS, satu-satunya solusi yang saya temukan untuk menangani symlink secara andal adalah dengan menggunakan
realpath
. Karena ini memerlukanbrew install coreutils
, saya baru saja mengotomatiskan langkah itu. Implementasi saya terlihat seperti ini:Kesalahan ini jika mereka tidak
brew
menginstal, tetapi Anda dapat menginstalnya juga. Saya hanya tidak merasa nyaman mengotomatiskan sesuatu yang menggulung kode ruby dari internet.Perhatikan bahwa ini merupakan variasi otomatis dari jawaban Oleg Mikheev .
Satu ujian penting
Salah satu pengujian yang bagus dari salah satu solusi ini adalah:
ln -s
) ke file ituApakah solusinya membedakan symlink, dan memberi Anda direktori aslinya? Jika demikian, itu berhasil.
sumber
Ini tampaknya berfungsi untuk OSX, tidak memerlukan binari apa pun, dan ditarik dari sini
sumber
Saya suka ini:
sumber
Aku butuh
realpath
pengganti pada OS X, salah satu yang beroperasi dengan benar pada jalur dengan symlink dan orangtua referensi sepertireadlink -f
Would . Ini termasuk menyelesaikan symlink di jalur sebelum menyelesaikan referensi induk; misalnya jika Anda telah menginstalcoreutils
botol homebrew , kemudian jalankan:Catatan yang
readlink -f
telah diselesaikan/tmp/linkeddir
sebelum menyelesaikan..
referensi dir induk. Tentu saja, tidak adareadlink -f
di Mac juga .Jadi sebagai bagian dari implementasi bash untuk
realpath
saya mengimplementasikan kembali apa yang dilakukan pemanggilancanonicalize_filename_mode(path, CAN_ALL_BUT_LAST)
fungsi GNUlib , di Bash 3.2; ini juga pemanggilan fungsi yang dilakukan GNUreadlink -f
:Ini mencakup deteksi symlink melingkar, keluar jika jalur (perantara) yang sama terlihat dua kali.
Jika yang Anda butuhkan hanyalah
readlink -f
, Anda dapat menggunakan cara di atas sebagai:Karena
realpath
, saya juga membutuhkan--relative-to
dan--relative-base
mendukung, yang memberi Anda jalur relatif setelah dikanonikalisasi:Saya menyertakan pengujian unit dalam permintaan Tinjauan Kode saya untuk kode ini .
sumber
Berdasarkan komunikasi dengan komentator, saya setuju bahwa ini sangat sulit dan tidak memiliki cara trival untuk mengimplementasikan realpath yang berperilaku sama seperti Ubuntu.
Tetapi versi berikut, dapat menangani kasus sudut, jawaban terbaik tidak bisa dan memenuhi kebutuhan harian saya di macbook. Masukkan kode ini ke ~ / .bashrc Anda dan ingat:
sumber
echo
. Lakukanpwd
hal yang sama sepertiecho $(pwd)
tanpa harus menelurkan salinan kedua dari cangkang. Juga, tidak mengutip argumen keecho
adalah bug (Anda akan kehilangan spasi kosong di depan atau di belakang, karakter spasi putih internal yang berdekatan, dan karakter pengganti diperluas, dll). Lihat lebih lanjut stackoverflow.com/questions/10067266/…realpath
direktori yang tidak ada.dir=$(dirname "$1"); file=$(basename "$1")
daripada sintaks backtick yang sudah lama usang. Juga perhatikan kutipan argumen yang benar, sekali lagi.