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.
%dlà số thiết bị, %ilà 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 statlỗi ném.
- Chém chém rất quan trọng. Nếu
foolà một symlink đến một thư mục, stat foosẽ kiểm tra symlink trong khi stat foo/sẽ kiểm tra thư mục. Hoặc nghiên cứu stat -Lvà sử dụng nó có thể.
--trong trường hợp $(pwd)hoặc $VARIABLE_PATHbắ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à realpathtiệ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:%isẽ cho bạn biết chúng giống nhau, nhưng readlinkhoặc realpathsẽ 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 -Lvà -Pcá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 stathoặc readlink -fnó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 statnó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/abccó thể khác hơn /moo/baz/abcbởi vì bất kỳ abccó 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, abccó 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/abcnhưng không /foo/bar/abc? Các tập tin cảm nhận sẽ khác nhau ngay cả khi statnó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 readlinkhoặc realpathhơn stat.
stat, readlinkVà realpathkhô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 cdmộ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 -Pcũng không phải là POSIX. Nếu bạn muốn shell POSIX "giả lập" set -P, hãy thay thế cdvà pwd:
cd() { command cd -P "$@"; }
pwd() { command pwd -P "$@"; }
POSIX yêu cầu tùy chọn cuối cùng -Phoặc -Lcó hiệu lực, do đó pwd -Lvẫ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\\nvì nó chỉ inode chứ không phải tên. Việcmaxdepth 0ngăn chặn một tìm kiếm sâu. Để an toàn hơn, hãy thêm%Dvì các nút chỉ là duy nhất cho mỗi đĩa, không phải trên toàn hệ thống.