Làm các đường dẫn sau chỉ đến cùng một vị trí đĩa?
/home/username
/app/home/username
Làm các đường dẫn sau chỉ đến cùng một vị trí đĩa?
/home/username
/app/home/username
Câu trả lời:
Thay đổi thư mục lần lượt cho từng cái và xem đầu ra của pwd -P
. Với -P
cờ, pwd
sẽ hiển thị thư mục làm việc hiện tại vật lý với tất cả các liên kết tượng trưng được giải quyết.
cd -P
để nhận được tên thư mục được giải quyết $PWD
) , nhưng nó không xử lý vấn đề của các thiết bị riêng biệt .
sd(){ set '' "$1" '' "${2?sd() requires two arguments!}"
while [ "$#" -gt 2 ]
do [ "${1:--L}" "${2:--L}" ${3:+"$4"} ] &&
[ "${1:--L}" ${3:+"-L"} "${3:-$4}" ] &&
[ "${2:-$3}" -ef "$4"/. ] && return || ${1:+"return"}
set "$@" "$2";shift 2;set ! "$@"
done 3>/dev/null 2>&"$((${#DBG}?2:3))"
}
sd()
Đầu tiên kiểm tra xem cả hai đối số của nó có phải là liên kết tượng trưng không, và nếu vậy, lần tiếp theo sẽ kiểm tra xem cả hai đối số đó có được liên kết với các thư mục có số inode và số thiết bị giống hệt nhau không. Nếu vậy, sd()
return
đúng
Không, điều đó kiểm tra xem cả hai không phải là liên kết tượng trưng, và, một lần nữa, nếu cả hai đều là các thư mục có số thiết bị và số inode bằng nhau. Không, nó trả về false.
Vì thế...
ln -s dir1 ln3; ln -s dir1 ln4; ln -s dir2 ln5
sd dir1 dir2; echo $?
1
sd dir1 ln3; echo $?
1
sd ln4 ln3; echo $?
0
sd ln4 ln5; echo $?
1
mount --bind dir1 dir2
sd dir1 dir2; echo $?
0
Có thể nên thực hiện mà không cần kiểm tra liên kết - ví dụ: nếu bạn muốn biết liệu mục tiêu của liên kết có giống với thư mục nào đó không, hoặc chỉ không quan tâm nếu đó là liên kết. Trong trường hợp đó, bạn sẽ chỉ cần một [ fname1 -ef fname2 ]
bài kiểm tra.
Ồ, tôi đoán tôi cũng nên đề cập rằng điều này giả định quyền tìm kiếm cho tất cả các đối số. Nó sẽ thất bại nếu người dùng gọi không có quyền cần thiết để chạy thử nghiệm.
Bạn không bao giờ có thể chắc chắn cơ chế hoặc hệ thống tệp ảo hoặc hệ thống tệp lớp phủ nào ở đó, để đồng bộ hóa các thư mục đó hoặc liên kết cái này với cái khác. Nếu đó là một liên kết tượng trưng đơn giản, các nút sẽ khác nhau. Để chắc chắn 100%, đó là cùng một vị trí, bạn có thể tạo một tệp trong /home/username
:
touch /home/username/.testfile
Và sau đó so sánh số lượng inode của tệp đó ở cả hai vị trí:
diff <(stat -c "%i" /home/username/.testfile) <(stat -c "%i" /app/home/username/.testfile)
Nếu chúng giống nhau, thì đó là cùng một tệp, do đó chúng trỏ đến cùng một vị trí.
Chà, ngay cả với điều đó bạn không thể chắc chắn 100%. Tất nhiên chúng có thể có cùng số inode bởi sự trùng hợp thuần túy, bởi vì trong cả hai tập tin, inode miễn phí tiếp theo có cùng một số ...
Có hai cách cơ bản để kiểm tra xem hai tệp có giống nhau không. Đầu tiên là kiểm tra xem đường dẫn của chúng có giống nhau không . Điều này không có dương tính giả, nhưng rất nhiều tiêu cực sai. Một trường hợp rõ ràng của phủ định sai là nếu liên kết tượng trưng có liên quan. Bạn có thể xử lý trường hợp đó bằng cách giải quyết các liên kết tượng trưng. Đối với các thư mục hiện có mà bạn có quyền thay đổi, điều này có thể được thực hiện với pwd -P
.
absolute_path1="$(cd -- "$path1" && pwd -P; echo .)" &&
absolute_path2="$(cd -- "$path2" && pwd -P; echo .)" &&
[ "$absolute_path1" = "$absolute_path2" ]
Việc bổ sung echo .
quan tâm đến trường hợp hiếm gặp khi một trong các mục tiêu có tên tệp kết thúc bằng một dòng mới: nếu dòng mới là ký tự cuối cùng của sự thay thế lệnh, thì nó sẽ bị tước, do đó đoạn trích sẽ báo cáo không chính xác foo
giống như foo
.
Vẫn có những tiêu cực giả tiềm ẩn. Với các thư mục, liên kết cứng không phải là mối quan tâm, bởi vì hầu hết các hệ điều hành và hệ thống tệp đều cấm các thư mục liên kết cứng. Điều có thể xảy ra là cùng một thư mục được cung cấp ở các vị trí khác nhau, chẳng hạn như:
gắn cùng một hệ thống tập tin từ xa ở hai vị trí khác nhau, ví dụ
mount server:/some/where /mnt1
mount server:/some/where /mnt2
compare /mnt1 /mnt2
Trong các ví dụ này, việc tranh luận liệu các thư mục có thực sự giống nhau hay không. Điều này cho thấy giới hạn của khái niệm về cùng một tập tin, trong các trường hợp cạnh.
Cách cơ bản thứ hai là kiểm tra nhận dạng được cung cấp bởi kernel: device và inode . Cuộc stat
gọi hệ thống báo cáo hai thuộc tính cho mỗi tệp:
st_dev
), theo truyền thống là nhận dạng của thiết bị khối (phân vùng đĩa) có chứa hệ thống tệp mà tệp đang bật;st_ino
), theo truyền thống là một số duy nhất xác định tệp trong cùng một hệ thống tệp.Thông thường, hai tệp giống hệt nhau khi và chỉ khi chúng có cùng số thiết bị và số inode. Dash, ksh, bash, zsh và ít nhất một số bản dựng BusyBox (nhưng không phải là POSIX sh) có một -ef
toán tử cho phần test
dựng sẵn kiểm tra rằng:
[ "$path1" -ef "$path2" ]
Điều này xử lý các liên kết cứng và liên kết tượng trưng một cách chính xác (các liên kết tượng trưng được theo dõi, tức là một liên kết tượng trưng đến một tệp được coi là giống như tệp đích).
Phương pháp này là đơn giản nhất để thực hiện, nếu shell của bạn (hoặc test
tiện ích của bạn ) hỗ trợ -ef
. Nhưng hãy cẩn thận rằng nó có dương tính giả, vì không phải tất cả các hệ thống tập tin đều báo cáo số inode duy nhất. Ví dụ, với các hệ thống tệp mạng, bạn có thể lựa chọn số inode của máy chủ từ xa. Nhiều hệ thống tập tin có thể xếp chồng báo cáo inode bên dưới, không phải là duy nhất nếu cây thư mục bên dưới kéo dài nhiều hệ thống tập tin.
Một cách tiếp cận khác là kiểm tra tính tương đương có thể quan sát được : sửa đổi một trong các thư mục và xem liệu sửa đổi có được phản ánh trong cái kia không. Cách tiếp cận này về nguyên tắc không có phủ định sai, nhưng nó đòi hỏi phải có quyền sửa đổi các thư mục và có thể phá vỡ các phần khác của hệ thống đang sử dụng các thư mục này. Có thể có dương tính giả, bởi vì nhìn thấy các sửa đổi được phản ánh có thể chỉ ra rằng có một daemon đồng bộ hóa các thư mục rất nhanh.
Giả sử /home/username
và /app/home/username
là các thư mục, bạn không thể kiểm tra số inode để xem chúng có cùng đường dẫn không. Điều này là do các thư mục không thể được liên kết cứng và các liên kết mềm có một nút khác.
Bạn có thể cd /home/username
, touch
một tập tin và xem nếu nó xuất hiện trong cái khác /app/home/username
. Có lẽ có những phương pháp tốt hơn, nếu ai đó có thể đi kèm với một câu trả lời tốt hơn xin vui lòng đi trước.
mount --bind
là một thư mục, điểm gắn kết sẽ được liệt kê với cùng một nút. Tương tự nếu bạn gắn một hệ thống tập tin tại hai vị trí. Tôi vừa kiểm tra cái này trên hệ thống có nguồn gốc từ Debian.
Mở rộng những gì marco đã nói: trên GNU / Linux ls -li /home/username /app/home/username
sẽ cung cấp cho bạn một gợi ý hay . Nếu cả hai nút đều có cơ hội như nhau thì chúng sẽ trỏ đến cùng một vị trí. Kiểm tra lại với mount
. Kiểm tra ba lần bằng cách touch
-ing một tập tin vào /home/username
và xem nếu nó xuất hiện trong /app/home/username
và với cùng một nút. Sau đó có thể khá chắc chắn đó là cùng một thư mục.
Thử nghiệm được thực hiện trên máy Linux Mint, hạt nhân chung 3.11.0-12:
# ls -ldi /var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /var
# mkdir /mnt/var
# ls -ldi /mnt/var
266483 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# mount --bind /var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# umount /mnt/var
# mount /dev/mapper/mint--vg-var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /mnt/var
Kết luận: Tôi nghĩ rằng bạn có thể kiểm tra các nút để đảm bảo hai thư mục giống hệt nhau miễn là chúng được gắn điểm. Nếu một là một liên kết tượng trưng, tất nhiên ở trên không áp dụng. Nhưng sau đó rõ ràng, phải:
# rmdir /mnt/var
# ln -s /var /mnt/
# ls -ldi /mnt/var
266483 lrwxrwxrwx 1 root root 4 jun 2 10:51 /mnt/var -> /var