realpathsepertinya tidak tersedia di Mac (OS X 10.11 "El Capitan"). :-(
Laryx Decidua
realpathtampaknya tidak tersedia di CentOS 6 baik
user5359531
6
di osx, brew install coreutilsakan membawarealpath
Kevin Chen
Di Ubuntu 18.04 saya, realpathsudah ada. Saya tidak perlu menginstalnya secara terpisah.
Acumenus
Anehnya, realpathtersedia di Git untuk Windows (bagi saya, setidaknya).
Andrew Keeton
104
Jika Anda telah menginstal paket coreutils, Anda biasanya dapat menggunakan readlink -f relative_file_nameuntuk mengambil yang absolut (dengan semua symlinks diselesaikan)
Perilaku untuk ini sedikit berbeda dari apa yang diminta pengguna, itu juga akan mengikuti dan menyelesaikan symlink rekursif di mana saja di jalan. Anda mungkin tidak menginginkannya dalam beberapa kasus.
meraba
1
@BradPeabody Ini berfungsi di Mac jika Anda menginstal coreutils dari homebrew brew install coreutils. Namun eksekusi dieksekusi oleh ag:greadlink -f relative_file_name
Miguel Isla
2
Perhatikan bahwa halaman manual readlink (1) memiliki kalimat pertama dari deskripsi: "Note realpath (1) adalah perintah yang lebih disukai untuk digunakan untuk fungsionalitas kanonikisasi."
josch
1
Anda dapat menggunakan -e bukannya -f untuk memeriksa apakah file / direktori ada atau tidak
readlink adalah solusi sederhana untuk linux, tetapi solusi ini juga berfungsi pada OSX, jadi +1
thetoolman
1
Skrip ini tidak setara dengan apa realpathatau apa yang readlink -fdilakukan. Misalnya, itu tidak berfungsi di jalur di mana komponen terakhir adalah symlink.
josch
2
@ josch: Pertanyaannya bukan tentang penyelesaian symlink. Tetapi jika Anda ingin melakukan itu, Anda dapat memberikan -Popsi untuk pwdperintah:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
4
Saya suka jawabannya, tetapi hanya berfungsi, jika pengguna diizinkan untuk cd ke direktori. Ini mungkin tidak selalu memungkinkan.
Matthias B
34
Untuk apa nilainya, saya memilih jawaban yang dipilih, tetapi ingin berbagi solusi. The downside adalah, itu hanya Linux - Saya menghabiskan sekitar 5 menit mencoba untuk menemukan setara OSX sebelum datang ke Stack overflow. Saya yakin itu di luar sana.
Di Linux Anda dapat menggunakannya readlink -ebersama-sama dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
hasil panen
/etc/
Dan kemudian Anda menggunakan dirnamesaudara perempuan, basenameuntuk mendapatkan nama file
Anda aman jika Anda menargetkan direktori, tidak basenameakan mengembalikan apa pun dan Anda hanya akan berakhir dengan garis miring ganda pada hasil akhir.
Entri yang sangat baik dengan dirname, readlink, dan basename. Itu membantu saya untuk mendapatkan jalur absolut dari tautan simbolik - bukan targetnya.
kevinarpe
Tidak berfungsi ketika Anda ingin mengembalikan jalur ke tautan simbolik (yang kebetulan harus saya lakukan ...).
Tomáš Zato - Reinstate Monica
Bagaimana Anda bisa menemukan jalur absolut ke jalur yang tidak ada?
synthesizerpatel
@synthesizerpatel Cukup mudah, saya akan berpikir; jika saya masuk /home/GKFXdan saya mengetik touch newfile, maka sebelum saya menekan enter Anda bisa mengetahui maksud saya "create / home / GKFX / newfile", yang merupakan jalur absolut ke file yang belum ada.
GKFX
25
Saya pikir ini yang paling portabel:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Tidak perlu melakukan cd kembali. Lihat stackoverflow.com/a/21188136/1504556 . Jawaban Anda adalah yang terbaik di halaman ini, IMHO. Bagi yang berminat tautan memberikan penjelasan mengapa solusi ini bekerja.
peterh
Ini tidak terlalu portabel, dirnameadalah utilitas inti GNU, tidak umum untuk semua yang belum saya percaya.
Ya Tuhan, terima kasih. Saya telah mencoba untuk memperbaiki versi yang digunakan ${1##*/}untuk sehari sekarang, dan sekarang saya mengganti sampah dengan basename "$1"itu tampaknya akhirnya benar-benar menangani jalur yang berakhiran /.
l3l_aze
NB, ini tidak melakukan hal yang benar dengan jalan berakhir pada../..
Alex Coventry
16
realpath mungkin yang terbaik
Tapi ...
Pertanyaan awal sangat membingungkan untuk memulai, dengan contoh yang buruk terkait dengan pertanyaan seperti yang dinyatakan.
Jawaban yang dipilih sebenarnya menjawab contoh yang diberikan, dan tidak sama sekali pertanyaan dalam judul. Perintah pertama adalah jawaban itu (benarkah? Aku ragu), dan bisa melakukannya tanpa '/'. Dan saya gagal melihat apa yang dilakukan perintah kedua.
Beberapa masalah beragam:
mengubah pathname relatif menjadi absolut, apa pun yang ditunjukkan, mungkin tidak ada. ( Biasanya, jika Anda mengeluarkan perintah seperti itu touch foo/bar, nama path foo/barharus ada untuk Anda, dan mungkin digunakan dalam perhitungan, sebelum file tersebut benar-benar dibuat. )
mungkin ada beberapa pathname absolut yang menunjukkan file yang sama (atau file potensial), terutama karena tautan simbolik (symlink) di path, tetapi mungkin karena alasan lain (perangkat mungkin dipasang dua kali lebih sebagai hanya baca). Seseorang mungkin atau mungkin tidak ingin menyelesaikan expllink symlinks tersebut.
sampai ke ujung rantai tautan simbolik ke file atau nama yang tidak memiliki tautan. Ini mungkin atau mungkin tidak menghasilkan nama jalur absolut, tergantung pada bagaimana hal itu dilakukan. Dan seseorang mungkin, atau mungkin tidak ingin menyelesaikannya menjadi pathname absolut.
Perintah readlink footanpa opsi memberikan jawaban hanya jika argumennya fooadalah tautan simbolik, dan jawaban itu adalah nilai symlink itu. Tidak ada tautan lain yang diikuti. Jawabannya mungkin jalur relatif: berapapun nilai argumen symlink.
Namun, readlinkmemiliki opsi (-f -e atau -m) yang akan bekerja untuk semua file, dan memberikan satu pathname absolut (yang tanpa symlink) ke file yang sebenarnya dilambangkan oleh argumen.
Ini berfungsi dengan baik untuk apa pun yang bukan symlink, meskipun orang mungkin ingin menggunakan pathname absolut tanpa menyelesaikan symlink menengah di path. Ini dilakukan oleh perintahrealpath -s foo
Dalam kasus argumen symlink, readlinkdengan opsinya lagi akan menyelesaikan semua symlink pada path absolut ke argumen, tetapi itu juga akan mencakup semua symlink yang mungkin ditemui dengan mengikuti nilai argumen. Anda mungkin tidak ingin itu jika Anda menginginkan jalur absolut ke argumen symlink itu sendiri, daripada ke apa pun yang ditautkan. Sekali lagi, jika foomerupakan symlink, realpath -s fooakan mendapatkan jalur absolut tanpa menyelesaikan symlink, termasuk yang diberikan sebagai argumen.
Tanpa -sopsi, realpathmelakukan hampir sama
readlink, kecuali hanya membaca nilai tautan, serta beberapa hal lainnya. Tidak jelas bagi saya mengapa readlinkmemiliki pilihan, menciptakan redundansi yang tampaknya tidak diinginkan dengan
realpath.
Menjelajahi web tidak banyak bicara, kecuali bahwa mungkin ada beberapa variasi di seluruh sistem.
Kesimpulan: realpathadalah perintah terbaik untuk digunakan, dengan fleksibilitas terbanyak, setidaknya untuk penggunaan yang diminta di sini.
Solusi favorit saya adalah yang oleh @EugenKonkov karena tidak menyiratkan keberadaan utilitas lain (paket coreutils).
Tetapi gagal untuk jalur relatif "." dan "..", jadi di sini adalah versi yang sedikit ditingkatkan menangani kasus-kasus khusus ini.
Masih gagal jika pengguna tidak memiliki izin untuk cdmasuk ke direktori induk dari jalur relatif.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Jika Anda menggunakan bash pada Mac OS X yang tidak memiliki realpath atau readlink -nya tidak dapat mencetak path absolut, Anda mungkin punya pilihan selain mengkode versi Anda sendiri untuk mencetaknya. Inilah implementasi saya:
(pesta murni)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(gunakan gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan jangka pendek terbatas. Penjelasan yang tepat akan sangat meningkatkan nilai jangka panjangnya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat bagi pembaca masa depan dengan pertanyaan lain yang serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat.
Ini berurusan dengan benar dengan kasus di mana elemen terakhir dari path .., dalam hal ini jawaban "$(pwd)/$(basename "$1")"in @ ernest-a akan muncul sebagai accurate_sub_path/spurious_subdirectory/...
Pada bash-4.3-p46, ini tidak berfungsi: shell mencetak baris kosong ketika saya menjalankandir=`cd ".."` && echo $dir
Michael
0
Ini adalah solusi berantai dari semua yang lain, misalnya, ketika realpathgagal, baik karena tidak diinstal atau karena keluar dengan kode kesalahan, maka, solusi berikutnya dicoba sampai mendapatkan jalur yang benar.
Saya tidak dapat menemukan solusi yang portabel rapi antara Mac OS Catalina, Ubuntu 16 dan Centos 7, jadi saya memutuskan untuk melakukannya dengan python inline dan itu bekerja dengan baik untuk skrip bash saya.
Jawaban:
menggunakan:
untuk mendapatkan semua file atau
untuk menampilkan jalur lengkap (jika jalur relatif penting)
sumber
$(pwd)
sebagai pengganti$PWD
? (ya, saya tahupwd
adalah builtin)Coba
realpath
.Untuk menghindari perluasan symlink, gunakan
realpath -s
.Jawabannya datang dari " perintah bash / fish untuk mencetak path absolut ke file ".
sumber
realpath
sepertinya tidak tersedia di Mac (OS X 10.11 "El Capitan"). :-(realpath
tampaknya tidak tersedia di CentOS 6 baikbrew install coreutils
akan membawarealpath
realpath
sudah ada. Saya tidak perlu menginstalnya secara terpisah.realpath
tersedia di Git untuk Windows (bagi saya, setidaknya).Jika Anda telah menginstal paket coreutils, Anda biasanya dapat menggunakan
readlink -f relative_file_name
untuk mengambil yang absolut (dengan semua symlinks diselesaikan)sumber
brew install coreutils
. Namun eksekusi dieksekusi oleh ag:greadlink -f relative_file_name
UPD Beberapa penjelasan
"$1"
dirname "$1"
cd "$(dirname "$1")
menuju dir relatif ini dan mendapatkan path absolut untuk itu dengan menjalankanpwd
perintah shell$(basename "$1")
echo
itusumber
realpath
atau apa yangreadlink -f
dilakukan. Misalnya, itu tidak berfungsi di jalur di mana komponen terakhir adalah symlink.-P
opsi untukpwd
perintah:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Untuk apa nilainya, saya memilih jawaban yang dipilih, tetapi ingin berbagi solusi. The downside adalah, itu hanya Linux - Saya menghabiskan sekitar 5 menit mencoba untuk menemukan setara OSX sebelum datang ke Stack overflow. Saya yakin itu di luar sana.
Di Linux Anda dapat menggunakannya
readlink -e
bersama-samadirname
.hasil panen
Dan kemudian Anda menggunakan
dirname
saudara perempuan,basename
untuk mendapatkan nama filehasil panen
Menyatukan semuanya ..
hasil panen
Anda aman jika Anda menargetkan direktori, tidak
basename
akan mengembalikan apa pun dan Anda hanya akan berakhir dengan garis miring ganda pada hasil akhir.sumber
dirname
,readlink
, danbasename
. Itu membantu saya untuk mendapatkan jalur absolut dari tautan simbolik - bukan targetnya./home/GKFX
dan saya mengetiktouch newfile
, maka sebelum saya menekan enter Anda bisa mengetahui maksud saya "create / home / GKFX / newfile", yang merupakan jalur absolut ke file yang belum ada.Saya pikir ini yang paling portabel:
Ini akan gagal jika jalurnya tidak ada.
sumber
dirname
adalah utilitas inti GNU, tidak umum untuk semua yang belum saya percaya.dirname
adalah utilitas standar POSIX, lihat di sini: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
untuk sehari sekarang, dan sekarang saya mengganti sampah denganbasename "$1"
itu tampaknya akhirnya benar-benar menangani jalur yang berakhiran /.../..
realpath
mungkin yang terbaikTapi ...
Pertanyaan awal sangat membingungkan untuk memulai, dengan contoh yang buruk terkait dengan pertanyaan seperti yang dinyatakan.
Jawaban yang dipilih sebenarnya menjawab contoh yang diberikan, dan tidak sama sekali pertanyaan dalam judul. Perintah pertama adalah jawaban itu (benarkah? Aku ragu), dan bisa melakukannya tanpa '/'. Dan saya gagal melihat apa yang dilakukan perintah kedua.
Beberapa masalah beragam:
mengubah pathname relatif menjadi absolut, apa pun yang ditunjukkan, mungkin tidak ada. ( Biasanya, jika Anda mengeluarkan perintah seperti itu
touch foo/bar
, nama pathfoo/bar
harus ada untuk Anda, dan mungkin digunakan dalam perhitungan, sebelum file tersebut benar-benar dibuat. )mungkin ada beberapa pathname absolut yang menunjukkan file yang sama (atau file potensial), terutama karena tautan simbolik (symlink) di path, tetapi mungkin karena alasan lain (perangkat mungkin dipasang dua kali lebih sebagai hanya baca). Seseorang mungkin atau mungkin tidak ingin menyelesaikan expllink symlinks tersebut.
sampai ke ujung rantai tautan simbolik ke file atau nama yang tidak memiliki tautan. Ini mungkin atau mungkin tidak menghasilkan nama jalur absolut, tergantung pada bagaimana hal itu dilakukan. Dan seseorang mungkin, atau mungkin tidak ingin menyelesaikannya menjadi pathname absolut.
Perintah
readlink foo
tanpa opsi memberikan jawaban hanya jika argumennyafoo
adalah tautan simbolik, dan jawaban itu adalah nilai symlink itu. Tidak ada tautan lain yang diikuti. Jawabannya mungkin jalur relatif: berapapun nilai argumen symlink.Namun,
readlink
memiliki opsi (-f -e atau -m) yang akan bekerja untuk semua file, dan memberikan satu pathname absolut (yang tanpa symlink) ke file yang sebenarnya dilambangkan oleh argumen.Ini berfungsi dengan baik untuk apa pun yang bukan symlink, meskipun orang mungkin ingin menggunakan pathname absolut tanpa menyelesaikan symlink menengah di path. Ini dilakukan oleh perintah
realpath -s foo
Dalam kasus argumen symlink,
readlink
dengan opsinya lagi akan menyelesaikan semua symlink pada path absolut ke argumen, tetapi itu juga akan mencakup semua symlink yang mungkin ditemui dengan mengikuti nilai argumen. Anda mungkin tidak ingin itu jika Anda menginginkan jalur absolut ke argumen symlink itu sendiri, daripada ke apa pun yang ditautkan. Sekali lagi, jikafoo
merupakan symlink,realpath -s foo
akan mendapatkan jalur absolut tanpa menyelesaikan symlink, termasuk yang diberikan sebagai argumen.Tanpa
-s
opsi,realpath
melakukan hampir samareadlink
, kecuali hanya membaca nilai tautan, serta beberapa hal lainnya. Tidak jelas bagi saya mengapareadlink
memiliki pilihan, menciptakan redundansi yang tampaknya tidak diinginkan denganrealpath
.Menjelajahi web tidak banyak bicara, kecuali bahwa mungkin ada beberapa variasi di seluruh sistem.
Kesimpulan:
realpath
adalah perintah terbaik untuk digunakan, dengan fleksibilitas terbanyak, setidaknya untuk penggunaan yang diminta di sini.sumber
Solusi favorit saya adalah yang oleh @EugenKonkov karena tidak menyiratkan keberadaan utilitas lain (paket coreutils).
Tetapi gagal untuk jalur relatif "." dan "..", jadi di sini adalah versi yang sedikit ditingkatkan menangani kasus-kasus khusus ini.
Masih gagal jika pengguna tidak memiliki izin untuk
cd
masuk ke direktori induk dari jalur relatif.sumber
Jawaban Eugen tidak berhasil bagi saya, tetapi ini berhasil:
Catatan, direktori kerja Anda saat ini tidak terpengaruh.
sumber
Solusi terbaik, imho, adalah yang diposting di sini: https://stackoverflow.com/a/3373298/9724628 .
Memang membutuhkan python untuk bekerja, tetapi tampaknya mencakup semua atau sebagian besar kasus tepi dan menjadi solusi yang sangat portabel.
sumber
Dalam hal
find
, mungkin paling mudah untuk memberikan jalur absolut untuk mencari, misalnya:sumber
Jika Anda menggunakan bash pada Mac OS X yang tidak memiliki realpath atau readlink -nya tidak dapat mencetak path absolut, Anda mungkin punya pilihan selain mengkode versi Anda sendiri untuk mencetaknya. Inilah implementasi saya:
(pesta murni)
(gunakan gawk)
(aws murni bsd)
contoh:
sumber
Apa yang mereka katakan, kecuali
find $PWD
atau (dalam bash)find ~+
sedikit lebih nyaman.sumber
Mirip dengan jawaban @ ernest-a tetapi tanpa memengaruhi
$OLDPWD
atau mendefinisikan fungsi baru Anda dapat memecat sebuah subkulit(cd <path>; pwd)
sumber
Jika jalur relatif adalah jalur direktori, maka coba milikku, harus menjadi yang terbaik:
sumber
sumber
Peningkatan ke versi @ ernest-a yang agak bagus:
Ini berurusan dengan benar dengan kasus di mana elemen terakhir dari path
..
, dalam hal ini jawaban"$(pwd)/$(basename "$1")"
in @ ernest-a akan muncul sebagaiaccurate_sub_path/spurious_subdirectory/..
.sumber
Jika Anda ingin mengubah variabel yang berisi jalur relatif menjadi jalur absolut, ini berfungsi:
"cd" menggema tanpa mengubah direktori kerja, karena dieksekusi di sini dalam sub-shell.
sumber
dir=`cd ".."` && echo $dir
Ini adalah solusi berantai dari semua yang lain, misalnya, ketika
realpath
gagal, baik karena tidak diinstal atau karena keluar dengan kode kesalahan, maka, solusi berikutnya dicoba sampai mendapatkan jalur yang benar.sumber
Anda bisa menggunakan substitusi string bash untuk jalur $ jalur relatif apa pun:
Substitusi front-of-string dasar mengikuti rumus
$ {string / # substring / replacement}
yang dibahas dengan baik di sini: https://www.tldp.org/LDP/abs/html/string-manipulation.html
The
\
karakter meniadakan/
ketika kita ingin menjadi bagian dari string yang kita temukan / ganti.sumber
Saya tidak dapat menemukan solusi yang portabel rapi antara Mac OS Catalina, Ubuntu 16 dan Centos 7, jadi saya memutuskan untuk melakukannya dengan python inline dan itu bekerja dengan baik untuk skrip bash saya.
sumber