Jawaban:
Anda dapat menggunakan readlink
utilitas, dengan -f
opsi:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Beberapa distribusi, misalnya yang menggunakan GNU coreutils dan FreeBSD , juga dilengkapi dengan realpath(1)
utilitas yang pada dasarnya hanya memanggil realpath(3)
dan melakukan hal yang hampir sama.
readlink
atau realpath
- Solaris dan HP-UX, pada khususnya.
brew install coreutils
apple.stackexchange.com/a/69332/23040 , dan jika Anda tidak ingin melakukan langkah yang mengalihkan semua alat standar CLI Mac ke setara GNU yang baru diinstal, cukup hubungi greadlink
.
Mudah dibawa, PWD
variabel diatur oleh shell ke satu lokasi absolut dari direktori saat ini. Komponen apa pun dari jalur itu dapat berupa tautan simbolis.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Jika Anda ingin menghilangkan .
dan ..
juga, ubah ke direktori yang berisi file dan dapatkan di $PWD
sana:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Tidak ada cara portabel untuk mengikuti tautan simbolik. Jika Anda memiliki jalur ke direktori, maka pada sebagian besar unices $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
menyediakan jalur yang tidak menggunakan tautan simbolik, karena shell yang melacak tautan simbolik cenderung diimplementasikan pwd -P
("P" untuk "fisik").
Beberapa perangkat menyediakan utilitas untuk mencetak jalur "fisik" ke file.
readlink -f
, seperti halnya FreeBSD ≥8.3, NetBSD ≥4.0, dan OpenBSD sejauh 2.2.realpath
(juga ada pada beberapa sistem Linux, dan itu ada di BusyBox).Jika Perl tersedia, Anda dapat menggunakan Cwd
modul .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Sepertinya tidak peduli dengan stdin.
||
Apakah pwd
sesuai dengan kebutuhan Anda? Ini memberikan jalur absolut dari direktori saat ini. Atau mungkin yang Anda inginkan adalah realpath () .
alister
dan rss67
dalam artikel ini memperkenalkan cara yang paling stabil, kompatibel dan termudah. Saya tidak pernah melihat cara yang lebih baik dari ini sebelumnya.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Jika Anda ingin kembali ke lokasi semula,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
atau
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Saya harap ini membantu. Ini solusi terbaik bagi saya.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Perhatikan tanda kutip ganda di sekitar substitusi (agar tidak pecah jika path berisi karakter spasi dan globbing) dan --
(jika path dimulai dengan -
). Ini juga hanya berfungsi untuk direktori, dan tidak mengkanoniskan tautan simbolik seperti yang diminta. Lihat jawaban saya untuk lebih jelasnya.
Jawaban lain di sini baik-baik saja tetapi tidak cukup untuk kebutuhan saya. Saya membutuhkan solusi yang dapat saya gunakan dalam skrip saya di mesin apa pun. Solusi saya adalah menulis skrip shell yang saya dapat meminta dari skrip di mana saya membutuhkannya.
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
Solusi ini ditulis untuk Bourne Shell untuk portabilitas. Saya memiliki ini dalam skrip bernama "respath.sh".
Script ini dapat digunakan seperti ini:
respath.sh '/path/to/file'
Atau seperti ini
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
Script menyelesaikan jalur dalam argumen pertama menggunakan jalur dari argumen kedua sebagai titik awal. Jika hanya argumen pertama yang disediakan, maka skrip menyelesaikan jalur relatif ke direktori kerja Anda saat ini.
pwd
builtin dan tidak mendukung -P
(Bourne shell tidak menerapkan bahwa $ PWD logis penanganan seperti kerang POSIX lakukan).
cd -P --
juga kalau-kalau argumen 1 berisi beberapa ..
case
Cek Anda seharusnya ..|../*)
bukan ..*
.
dirname $cwd
Dalam hal, tambahan, Anda memiliki beberapa jalur yang telah ditentukan untuk $1
(biasanya ${PWD}
), berikut ini akan berfungsi:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
Menghormati orang lain menjawab, saya menemukan fungsi di bawah ini menjadi lebih mudah dan portabel antara linux / MAC OSX daripada yang lain yang saya temukan di mana-mana. Mungkin bisa membantu seseorang.
#!/usr/bin/bash
get_absolute_path(){
file_path=`pwd $1`
echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
Anggap variabel a menyimpan nama jalur (a = "apa pun")
1. Untuk jalur yang mengandung ruang potensial:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Untuk pertanyaan aktual, yaitu mengonversi jalur ke absolut: readlink dapat mengambil konten symlink, yang dapat digunakan sebagai berikut. (note readlink -f
akan sempurna tetapi tidak tersedia di setidaknya Mac OS X bash, di mana -f singkatan FORMATS .)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Baru dipelajari pwd -P
di man pwd
: -P adalah untuk " Menampilkan direktori kerja saat ini fisik (semua tautan simbolik diselesaikan) " dan karenanya
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
akan bekerja juga.
Kesimpulan: gabungkan 1 dengan 2 untuk memenuhi kedua kebutuhan Anda, sementara nama jalur yang mengandung ruang sudah diurus dalam yang lebih ringkas 3 .
-f
switch tidak ada pada Mac OS X (setidaknya dari 10.8.5). Tanpa-f
sakelar, ia hanya mengembalikan kode kesalahan.