Câu trả lời khác này đề cập stat
. Hãy cải thiện cách tiếp cận:
a="$(stat --format=%d:%i -- "$(pwd)/expected-subdir/")" || printf "Error A\n" >&2
b="$(stat --format=%d:%i -- "$VARIABLE_PATH/expected-subdir/")" || printf "Error B\n" >&2
[ "$a" = "$b" ] || printf "Not the same path.\n" >&2
Ghi chú:
- Chúng tôi đang sử dụng
stat --format=
, vì vậy không cần phân tích cú pháp nữa.
%d
là số thiết bị, %i
là số inode. Chỉ riêng cái sau là không đủ vì hai đối tượng trên các thiết bị khác nhau (hệ thống tệp) có thể có cùng số inode.
- Vỏ đủ thông minh để xử lý riêng báo giá bên trong và bên ngoài
$( )
.
printf
-s chỉ là sơ khai để xử lý lỗi. Trong kịch bản thực, bạn có thể muốn một cái gì đó như
[ "$a" = "$b" ] || { printf "Not the same path.\n" >&2; exit 2; }
Đường dẫn không tồn tại sẽ làm cho stat
lỗi ném.
- Chém chém rất quan trọng. Nếu
foo
là một symlink đến một thư mục, stat foo
sẽ kiểm tra symlink trong khi stat foo/
sẽ kiểm tra thư mục. Hoặc nghiên cứu stat -L
và sử dụng nó có thể.
--
trong trường hợp $(pwd)
hoặc $VARIABLE_PATH
bắt đầu bằng -
(xem hướng dẫn 10 ở đây ).
Có readlink -f
(cũng được đề cập trong câu trả lời khác) và realpath
tiện ích. Một trong số đó có thể là một cách tiếp cận tốt hơn stat
. Nó phụ thuộc vào khía cạnh nào của các con đường là quan trọng đối với bạn. Sự khác biệt chính:
- Nếu
/foo/bar/
là một liên kết gắn kết /moo/baz/
sau đó stat --format=%d:%i
sẽ cho bạn biết chúng giống nhau, nhưng readlink
hoặc realpath
sẽ xem xét chúng khác nhau.
- Tình hình trở nên phức tạp với các liên kết tượng trưng và
..
. Xem man 1 realpath
, đặc biệt -L
và -P
các tùy chọn.
Với các liên kết tượng trưng có liên quan, nếu tập lệnh của bạn thay đổi thư mục lên ( /
ví dụ: hướng tới cd ..
), bạn có thể nhận được các kết quả khác nhau tùy thuộc vào nơi bạn bắt đầu, ngay cả khi stat
hoặc readlink -f
nói hai điểm bắt đầu giống nhau (so sánh Tại sao lại ls ..
hiển thị nội dung cha mẹ thực sự khi tôi ' m bên trong một thư mục liên kết tượng trưng? ). Hãy xem xét phương pháp này:
# early in the script
set -P
cd . # seems like no-op but updates the PWD variable to physical path
Với các liên kết gắn kết có liên quan, nếu tập lệnh của bạn thay đổi thư mục, bạn có thể nhận được các kết quả khác nhau tùy thuộc vào nơi bạn bắt đầu, ngay cả khi stat
nói hai điểm bắt đầu giống nhau. Xem xét ví dụ với /foo/bar/
và /moo/baz/
(đã được giới thiệu ở trên). Rõ ràng nó /foo/
có thể hoàn toàn khác /moo/
. Nhưng cũng /foo/bar/abc
có thể khác hơn /moo/baz/abc
bởi vì bất kỳ abc
có thể là một gắn kết độc lập với một cái gì đó khác. Vì vậy, không chỉ cd ..
có thể đặt bạn ở một vị trí khác, mà còn cd abc
.
Vâng, abc
có thể là một tập tin. Điều gì nếu bạn liên kết một tập tin khác /moo/baz/abc
nhưng không /foo/bar/abc
? Các tập tin cảm nhận sẽ khác nhau ngay cả khi stat
nói rằng bạn đang ở cùng một nơi!
Bởi vì những vấn đề này bạn thực sự có thể thích readlink
hoặc realpath
hơn stat
.
stat
, readlink
Và realpath
không được yêu cầu của POSIX. Trong trường hợp của bạn, một giải pháp di động có thể trông như thế này:
a="$(cd -P -- "expected-subdir" && pwd -P)" || exit 1
b="$(cd -P -- "$VARIABLE_PATH/expected-subdir" && pwd -P)" || exit 1
[ "$a" = "$b" ] || { printf "Not the same path.\n" >&2; exit 2; }
Nó hoạt động bằng cách - theo cd
một trong hai đường dẫn và truy xuất nó với pwd
. Các hoạt động này rõ ràng bị buộc phải hành động "vật lý" ( -P
).
set -P
cũng không phải là POSIX. Nếu bạn muốn shell POSIX "giả lập" set -P
, hãy thay thế cd
và pwd
:
cd() { command cd -P "$@"; }
pwd() { command pwd -P "$@"; }
POSIX yêu cầu tùy chọn cuối cùng -P
hoặc -L
có hiệu lực, do đó pwd -L
vẫn truy xuất đường dẫn logic mặc dù chức năng "tiêm" -P
; giống nhau cho cd -L
.
find path/to/dir/ -maxdepth 0 -printf %i\\n
vì nó chỉ inode chứ không phải tên. Việcmaxdepth 0
ngăn chặn một tìm kiếm sâu. Để an toàn hơn, hãy thêm%D
vì các nút chỉ là duy nhất cho mỗi đĩa, không phải trên toàn hệ thống.