Làm thế nào để tìm hiểu xem hai thư mục trỏ đến cùng một vị trí


8

Làm các đường dẫn sau chỉ đến cùng một vị trí đĩa?

/home/username
/app/home/username

Không có câu trả lời phổ quát; nó phụ thuộc vào cách hệ thống của bạn được cấu hình.
G-Man nói 'Tái lập Monica'

@ G-Man - Unix được xây dựng trên fs của nó, và rằng được xây dựng trên số serial - hoặc inodes . (wikipedia thậm chí trích dẫn Dennis Ritchie về từ nguyên của nó ) . Mặc dù các nút thiết bị cụ thể, nhưng các thiết bị đó có cùng số siêu số riêng của chúng theo số thiết bị. Ngay cả trên các hệ thống cho phép bạn vào các thư mục liên kết cứng - tất cả các liên kết vẫn là cùng một thư mục vì chúng chia sẻ cùng một nút trên cùng một thiết bị. Bạn có thể dễ dàng kiểm tra điều này trên bất kỳ hệ thống Unix nào.
mikeerv

Câu trả lời:


7

Thay đổi thư mục lần lượt cho từng cái và xem đầu ra của pwd -P. Với -Pcờ, pwdsẽ 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.


Mặc dù đúng, (mặc dù bạn chỉ có thể sử dụng 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 .
mikeerv

Vấn đề của các thiết bị riêng biệt là gì?
Kusalananda

3
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.


1

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ố ...


2
Bạn cần kiểm tra số thiết bị cùng với số inode. Chỉ riêng số inode là không đủ.
Gilles 'SO- ngừng trở nên xấu xa'

1

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
    
  • Một gắn kết ràng buộc

  • Bất kỳ hệ thống tập tin có thể xếp chồng nào, tức là một cách để trình bày một hệ thống tập tin theo một cách khác, trong đó bạn coi chế độ xem của thư mục là không thay đổi đủ so với ban đầu mà nó thực sự là cùng một thư mục. Ví dụ: hệ thống tệp có thể xếp chồng có thể chuyển đổi tên tệp và tên của thư mục là bất biến theo chuyển đổi.

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 statgọi hệ thống báo cáo hai thuộc tính cho mỗi tệp:

  • số thiết bị ( 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;
  • số inode ( 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 -eftoán tử cho phần testdự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 testtiệ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.


0

Giả sử /home/username/app/home/usernamelà 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, touchmộ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.


1
Điều này không hoàn toàn đúng. Nếu bạn mount --bindlà 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 Bạn có thể kiểm tra inode. Tất nhiên, nếu một trong hai đường dẫn là một liên kết tượng trưng, ​​bạn sẽ cần kiểm tra mục tiêu của nó.
Gilles 'SO- đừng trở nên xấu xa'

0

Mở rộng những gì marco đã nói: trên GNU / Linux ls -li /home/username /app/home/usernamesẽ 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/usernamevà xem nếu nó xuất hiện trong /app/home/username 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.