Pertanyaan: apakah ada perintah sh / bash / zsh / fish / ... sederhana untuk mencetak jalur absolut dari file mana pun yang saya beri makan?
Kasus penggunaan: Saya dalam direktori /a/b
dan saya ingin mencetak path lengkap ke file c
pada baris perintah sehingga saya dapat dengan mudah sisipkan ke program lain: /a/b/c
. Sederhana, namun sedikit program untuk melakukan ini mungkin bisa menyelamatkan saya 5 atau lebih detik ketika datang untuk menangani jalur panjang, yang pada akhirnya bertambah. Jadi itu mengejutkan saya bahwa saya tidak dapat menemukan utilitas standar untuk melakukan ini - apakah benar-benar tidak ada?
Berikut contoh implementasi, abspath.py:
#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
Jawaban:
Coba
realpath
.sumber
realpath
terdiri dari: github.com/westonruter/misc-cli-tools/blob/master/realpathCoba
readlink
yang akan menyelesaikan tautan simbolik:sumber
-m
adalah pilihan terbaik untuk digunakan./usr/bin/readlink
di Mavericks. Atau maksud Anda opsi-opsi itu tidak ditemukan di OS X? Tampaknya menjadi versi BSD kerdil ...: preadlink
manual BSDonly the target of the symbolic link is printed. If the given argument is not a symbolic link, readlink will print nothing and exit with an error
:, jadi readlink tidak akan berfungsi untuk tujuan ini di OSXsumber
a b
(dua spasi antara a dan b, jadi makanlah salah satunya).function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }
membuat sendirirealpath
perintah (jawaban yang saat ini diterima) di OS X. Terima kasih!LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
Lupakan
readlink
danrealpath
yang mungkin atau mungkin tidak diinstal pada sistem Anda.Memperluas jawaban dogbane di atas di sini dinyatakan sebagai fungsi:
Anda dapat menggunakannya seperti ini:
Bagaimana dan mengapa ini bekerja?
Solusinya mengeksploitasi fakta bahwa Bash built-in
pwd
command akan mencetak path absolut dari direktori saat ini ketika dipanggil tanpa argumen.Mengapa saya suka solusi ini?
Ini portabel dan tidak memerlukan keduanya
readlink
ataurealpath
yang sering tidak ada pada instalasi default distro Linux / Unix yang diberikan.Bagaimana jika dir tidak ada?
Seperti yang diberikan di atas, fungsi akan gagal dan mencetak pada stderr jika jalur direktori yang diberikan tidak ada. Ini mungkin bukan yang Anda inginkan. Anda dapat memperluas fungsi untuk menangani situasi itu:
Sekarang ia akan mengembalikan string kosong jika salah satu dir induk tidak ada.
Bagaimana Anda menangani trailing '..' atau '.' dalam input?
Yah, itu memang memberikan jalan absolut dalam kasus itu, tetapi tidak sedikit. Ini akan terlihat seperti:
Jika Anda ingin menyelesaikan '..' Anda harus membuat skrip seperti:
sumber
realpath
berasal dari paket coreutils, yang juga berisi alat-alat sepertiwho
,touch
ataucat
. Ini adalah seperangkat alat GNU yang cukup standar, sehingga Anda dapat yakin bahwa ini diinstal pada hampir semua mesin berbasis linux. Yang mengatakan, Anda benar: ada 2 masalah dengan itu: i) Anda mungkin akan melewatkannya di instal default pada sistem non GNU unix (seperti OpenBSD) ii) alat ini diperkenalkan di versi 8.15 (jadi ini cukup baru, mulai 2012), jadi Anda akan melewatkannya di sistem stabil jangka panjang (seperti RHEL 6).Ini lebih baik daripada
readlink -e FILE
ataurealpath
, karena berfungsi bahkan jika file tidak ada.sumber
-m
opsi ini tidak tersedia di Mavericks.Jalur relatif ini ke fungsi shell konverter jalur absolut
cd
danpwd
)..
dan.
Kode:
Sampel:
Catatan: Ini didasarkan pada jawaban dari nolan6000 dan bsingh , tetapi memperbaiki kasus file.
Saya juga mengerti bahwa pertanyaan awal adalah tentang utilitas baris perintah yang ada. Tapi karena ini sepertinya pertanyaan THE pada stackoverflow untuk itu termasuk skrip shell yang ingin memiliki dependensi minimal, saya meletakkan solusi skrip ini di sini, jadi saya bisa menemukannya nanti :)
sumber
$ abspath 'a b c/file.txt'
Itu karena argumen untukcd
tidak dikutip. Untuk mengatasi ini, alih-alih mengutip seluruh argumen untukecho
(adakah alasan untuk kutipan ini?) Hanya mengutip argumen path. Yaitu gantiecho "$(cd ${1%/*}; pwd)/${1##*/}"
denganecho $(cd "${1%/*}"; pwd)/${1##*/}
.echo "$(cd "$1"; pwd)"
dengan(cd "$1"; pwd)
. Tidak perlu gema di sini.( ... )
masih diperlukan, jadi itucd
terjadi dalam subkulit, karena kami tidak ingin mengubah direktori kerja untuk pemanggilabspath
.The
find
perintah dapat membantuDaftar semua file di atau di bawah direktori saat ini dengan nama yang cocok dengan polanya. Anda dapat menyederhanakannya jika Anda hanya akan mendapatkan beberapa hasil (misalnya direktori di dekat bagian bawah pohon yang berisi beberapa file), adil
Saya menggunakan ini pada Solaris 10, yang tidak memiliki utilitas lain yang disebutkan.
sumber
PWD
, Anda bisa menggunakannya$PWD/$filename
.Jika Anda tidak memiliki utilitas readlink atau realpath daripada Anda dapat menggunakan fungsi berikut yang bekerja di bash dan zsh (tidak yakin tentang yang lain).
Ini juga berfungsi untuk file yang tidak ada (seperti halnya fungsi python
os.path.abspath
).Sayangnya
abspath ./../somefile
tidak menghilangkan titik-titik.sumber
echo "$1"
denganprintf "%s\n" "$1"
(sama dengan gema kedua).echo
dapat menafsirkan garis miring terbalik di dalam argumennya.Berikut ini adalah fungsi zsh-only yang saya sukai karena kekompakannya. Ia menggunakan pengubah ekspansi 'A' - lihat zshexpn (1).
sumber
Ada hal umumnya tidak ada seperti yang
absolute path
ke file (pernyataan ini berarti bahwa mungkin ada lebih dari satu pada umumnya, maka penggunaan artikel yang pasti yang tidak tepat). Anabsolute path
adalah setiap jalur yang dimulai dari root "/" dan menunjuk file tanpa ambiguitas secara independen dari direktori kerja. (Lihat misalnya wikipedia ).A
relative path
adalah jalur yang harus ditafsirkan mulai dari direktori lain. Ini mungkin direktori kerja jikarelative path
sedang dimanipulasi oleh aplikasi (meskipun tidak harus). Ketika berada di tautan simbolis dalam direktori, umumnya dimaksudkan untuk relatif terhadap direktori itu (meskipun pengguna mungkin memiliki kegunaan lain dalam pikiran).Karenanya path absolut hanyalah path relatif ke direktori root.
Jalur (absolut atau relatif) mungkin mengandung atau tidak mengandung tautan simbolik. Jika tidak, itu juga agak tahan terhadap perubahan dalam struktur yang menghubungkan, tetapi ini tidak selalu diperlukan atau bahkan diinginkan. Beberapa orang memanggil
canonical path
(ataucanonical file name
atauresolved path
) suatuabsolute path
di mana semua tautan simbolik telah dipecahkan, yaitu telah diganti oleh jalur ke mana pun tautan itu. Perintahrealpath
danreadlink
keduanya mencari jalur kanonik, tetapi hanyarealpath
memiliki opsi untuk mendapatkan jalur absolut tanpa repot-repot menyelesaikan tautan simbolik (bersama dengan beberapa opsi lain untuk mendapatkan berbagai jenis jalur, absolut atau relatif ke beberapa direktori).Ini membutuhkan beberapa komentar:
realpath
danreadlink
memiliki opsi untuk menjelaskannya.canonical
. Karenanya konsep ini bergantung pada waktu (atau lingkungan).canonical path
ke file, karena dua alasan:ro
) pada beberapa titik pemasangan.Oleh karena itu, bahkan dengan definisi yang jauh lebih ketat
canonical path
, mungkin ada beberapa jalur kanonik ke file. Ini juga berarti bahwa kualifikasicanonical
agak tidak memadai karena biasanya menyiratkan gagasan tentang keunikan.Ini memperluas diskusi singkat tentang topik dalam jawaban untuk pertanyaan serupa lainnya di Bash: mengambil jalur absolut yang diberikan relatif
Kesimpulan saya adalah yang
realpath
dirancang lebih baik dan jauh lebih fleksibel daripadareadlink
. Satu-satunya penggunaanreadlink
yang tidak tercakuprealpath
adalah panggilan tanpa opsi mengembalikan nilai tautan simbolik.sumber
realpath
vsreadlink
atau bahkan tentang tautan simbolis adalah surplus untuk apa yang saya minta.canonical
merujuk tepatnya pada keunikan ini relatif terhadap serangkaian transformasi. Tetapi, misalnya, / dev / cdrom adalah path absolut yang sangat bagus, meskipun sebenarnya itu adalah tautan ke / dev / sr0. Keduanya menunjuk ke perangkat yang sama. Jawaban asli saya menunjuk ke artikel web yang relevan.The
dogbane
jawabannya dengan deskripsi apa yang menimpa:Penjelasan:
"$1"
dirname "$1"
cd "$(dirname "$1")
ke dir relatif ini dan mendapatkan path absolut untuk itu dengan menjalankanpwd
perintah shell$(basename "$1")
echo
itusumber
Untuk direktori
dirname
tersandung../
dan kembali./
.Fungsi nolan6000 dapat dimodifikasi untuk memperbaikinya:
sumber
.profile
dan karenanya tersedia untuk penggunaan interaktif.$1
nama file polos:get_abs_filename foo
-> tidak ada (atau<current_dir>/foo/foo
jikafoo
direktori).Ini bukan jawaban untuk pertanyaan, tetapi bagi mereka yang menulis:
ia menangani / ... ... dll dengan benar. Saya juga tampaknya bekerja di OSX
sumber
Saya telah menempatkan skrip berikut pada sistem saya & saya menyebutnya sebagai bash alias ketika saya ingin dengan cepat mengambil path lengkap ke file di dir saat ini:
Saya tidak yakin mengapa, tetapi, pada OS X ketika dipanggil oleh skrip "$ PWD" meluas ke jalur absolut. Ketika perintah find dipanggil pada baris perintah, itu tidak. Tapi itu melakukan apa yang saya inginkan ... nikmati.
sumber
$PWD
selalu memiliki jalur absolut direktori kerja. Juga,find
tidak akan mentolerir garis miring, jadi Anda tidak menjawab pertanyaan seperti yang diajukan. Cara yang lebih cepat untuk melakukan apa yang Anda ingin lakukan hanyalahecho "$PWD/$1"
Yang paling sederhana jika Anda hanya ingin menggunakan builtin adalah:
Hanya dua kata tambahan untuk diketik, dan ini akan bekerja pada semua sistem unix, serta OSX.
sumber
-maxdepth 1
sebelumnya-name
(seandainya file ada di direktori saat ini). Tanpa itu ia akan bekerja dengan file di subdirektori pwd, tetapi tidak dengan yang lain.find
tidak akan menemukan file di luar pohon direktori di bawahnyapwd
. Misalnya, jika Anda mencobafind . -name ../existingFile
, itu gagal.Ini menebus kekurangan
realpath
, menyimpannya dalam skrip shellfullpath
. Anda sekarang dapat menelepon:sumber
realpath "foo bar"
->/home/myname/foo bar
. Jika Anda tidak dapat repot mengutip argumen baris perintah, itu bukanrealpath
salah.Alternatif untuk mendapatkan path absolut di Ruby :
realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}
Bekerja tanpa argumen (folder saat ini) dan path file atau folder relatif dan absolut sebagai agumen.
sumber
Jawab dengan Homebrew
realpath
adalah jawaban terbaik, tetapi jika Anda belum menginstalnya, Anda harus terlebih dahulu menjalankanbrew install coreutils
yang akan menginstal coreutils dengan banyak fungsi luar biasa. Menulis fungsi khusus dan mengekspornya terlalu banyak pekerjaan dan berisiko kesalahan untuk sesuatu seperti ini, berikut adalah dua baris:sumber
Hai teman-teman, saya tahu ini adalah utas lama tetapi saya hanya memposting ini untuk referensi kepada orang lain yang mengunjungi ini seperti saya. Jika saya mengerti pertanyaan dengan benar, saya pikir
locate $filename
perintahnya. Ini menampilkan jalur absolut dari file yang disediakan, tetapi hanya jika ada.sumber
locate
adalah utilitas untuk mencari file / jalur dengan nama. Mungkin melakukan pekerjaan tetapi juga dapat menemukan kecocokan lain dan mungkin tidak menemukan file yang ada tanpa memanggilupdatedb
sebagai root terlebih dahulu.