Câu trả lời:
Bạn có thể sử dụng readlink
tiện ích, với -f
tùy chọn:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Một số bản phân phối, ví dụ như các bản phân phối sử dụng GNU coreutils và FreeBSD , cũng đi kèm với một realpath(1)
tiện ích về cơ bản chỉ gọi realpath(3)
và thực hiện khá nhiều điều tương tự.
readlink
hay realpath
- Solaris và HP-UX, nói riêng.
brew install coreutils
apple.stackexchange.com/a/69332/23040 và nếu bạn không muốn thực hiện bước chuyển hướng tất cả các công cụ Mac CLI tiêu chuẩn sang tương đương GNU mới được cài đặt, chỉ cần gọi greadlink
.
Có thể, PWD
biến được đặt bởi shell thành một vị trí tuyệt đối của thư mục hiện tại. Bất kỳ thành phần nào của đường dẫn đó có thể là một liên kết tượng trưng.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Nếu bạn muốn loại bỏ .
và ..
cũng vậy, thay đổi thư mục chứa tệp và lấy $PWD
ở đó:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Không có cách di động để theo các liên kết tượng trưng. Nếu bạn có một đường dẫn đến một thư mục, thì trên hầu hết các thông báo $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
sẽ cung cấp một đường dẫn không sử dụng các liên kết tượng trưng, bởi vì các trình tự theo dõi các liên kết tượng trưng có xu hướng thực hiện pwd -P
(Bối cảnh cho các vật lý của Rằng ).
Một số thông báo cung cấp một tiện ích để in đường dẫn vật lý của thành một tập tin.
readlink -f
như FreeBSD ≥8.3, NetBSD ≥4.0 và OpenBSD cho đến tận 2.2.realpath
(nó cũng có mặt trên một số hệ thống Linux và có trong BusyBox).Nếu Perl có sẵn, bạn có thể sử dụng Cwd
mô-đun .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Nó dường như không quan tâm đến stdin.
||
Có pwd
phù hợp với nhu cầu của bạn? Nó cho đường dẫn tuyệt đối của thư mục hiện tại. Hoặc có thể những gì bạn muốn là realpath () .
alister
và rss67
trong bài viết này giới thiệu cách ổn định nhất, tương thích và dễ dàng nhất. Tôi chưa bao giờ thấy cách tốt hơn thế này trước đây.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Nếu bạn muốn quay lại vị trí ban đầu,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
hoặc là
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Tôi muốn điều này giúp. Đây là giải pháp tốt nhất cho tôi.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Lưu ý các dấu ngoặc kép xung quanh sự thay thế (để không bị phá vỡ nếu đường dẫn chứa các khoảng trắng và ký tự nối tiếp) và --
(trong trường hợp đường dẫn bắt đầu bằng -
). Ngoài ra, điều này chỉ hoạt động cho các thư mục, và không hợp thức hóa các liên kết tượng trưng theo yêu cầu. Xem câu trả lời của tôi để biết thêm chi tiết.
Các câu trả lời khác ở đây là tốt nhưng không đủ cho nhu cầu của tôi. Tôi cần một giải pháp mà tôi có thể sử dụng trong các tập lệnh của mình trên bất kỳ máy nào. Giải pháp của tôi là viết một kịch bản shell mà tôi có thể gọi từ các kịch bản mà tôi cần.
#!/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
Giải pháp này được viết cho Bourne Shell cho tính di động. Tôi có cái này trong một kịch bản có tên là "respath.sh".
Kịch bản này có thể được sử dụng như thế này:
respath.sh '/path/to/file'
Hay như thế này
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
Kịch bản giải quyết đường dẫn trong đối số thứ nhất bằng cách sử dụng đường dẫn từ đối số thứ hai làm điểm bắt đầu. Nếu chỉ cung cấp đối số đầu tiên, thì tập lệnh sẽ giải quyết đường dẫn liên quan đến thư mục làm việc hiện tại của bạn.
pwd
và không hỗ trợ -P
(vỏ Bourne không triển khai xử lý $ PWD hợp lý như các vỏ POSIX).
cd -P --
trong trường hợp đối số thứ nhất chứa một số ..
case
Kiểm tra của bạn nên được ..|../*)
thay vì ..*
.
dirname $cwd
Ngoài ra, trong trường hợp, bạn có một số đường dẫn được xác định trước cho $1
(thông thường ${PWD}
), sau đây sẽ hoạt động:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
Tôn trọng câu trả lời của mọi người khác, tôi thấy chức năng bên dưới rất dễ dàng và di động giữa linux / MAC OSX so với các ứng dụng khác tôi tìm thấy ở mọi nơi. Có thể giúp ai đó.
#!/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
Giả sử biến a lưu tên đường dẫn (a = "sao cũng được)
1. Đối với đường dẫn chứa không gian tiềm năng:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Đối với câu hỏi thực tế, tức là chuyển đổi đường dẫn thành tuyệt đối: readlink có thể truy xuất nội dung symlink, có thể được sử dụng như sau. (lưu ý readlink -f
sẽ là hoàn hảo nhưng không có sẵn trong bash Mac OS X, trong đó -f là viết tắt của FORMATS .)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Chỉ học pwd -P
trong man pwd
: -P là " Hiển thị thư mục làm việc hiện tại vật lý (tất cả các liên kết tượng trưng đã được giải quyết) " và do đó
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
cũng sẽ làm việc
Kết luận: kết hợp 1 với 2 để đáp ứng cả hai yêu cầu của bạn, trong khi các tên đường dẫn chứa không gian đã được xử lý trong 3 ngắn gọn hơn .
-f
tắc không tồn tại trên Mac OS X (ít nhất là vào ngày 10.8.5). Không có công-f
tắc, nó chỉ trả về mã lỗi.