Làm thế nào tôi có thể kiểm tra nếu /my/dir
trên cùng một phân vùng như /
?
Điều này là để tích hợp trong một kịch bản. Gắn kết nên được xử lý chính xác. Giải pháp tương thích POSIX được chào đón.
Làm thế nào tôi có thể kiểm tra nếu /my/dir
trên cùng một phân vùng như /
?
Điều này là để tích hợp trong một kịch bản. Gắn kết nên được xử lý chính xác. Giải pháp tương thích POSIX được chào đón.
Câu trả lời:
Bạn có thể kiểm tra điều này với stat:
$ stat -c '%d %m' /proc/sys/
3 /proc
Hiển thị cho bạn số thiết bị và nơi thư mục của bạn được gắn kết.
stat
lệnh shell không phải là POSIX ...
Lệnh sau đây cung cấp một tên duy nhất cho điểm gắn kết chứa tệp $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Điều này hoạt động trên bất kỳ hệ thống POSIX . Các -P
tùy chọn áp đặt một định dạng có thể dự đoán; trường đầu tiên của dòng thứ hai là tên hệ thống tập tin tên lửa. Do đó, để kiểm tra hai tệp nằm dưới cùng một điểm gắn kết:
if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
"$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Hoặc, để lưu một vài lời mời quy trình:
if df -P -- "$file1" "$file2" |
awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Một vài hệ điều hành có thể có khoảng trắng trong tên âm lượng. Không có cách hoàn toàn đáng tin cậy để phân tích df
đầu ra trong trường hợp này.
Trong phần mềm này, bạn có thể xác định hệ thống tệp chứa tệp theo st_dev
trường được trả về stat
. Không có cách di động để làm điều này từ một kịch bản shell. Một số hệ thống có một stat
tiện ích, nhưng cú pháp của nó khác nhau:
stat
báo cáo st_dev
trường khi được gọi là stat -c %D -- "$file"
.stat
tương thích với lõi GNU. Những người khác có stat
mà không có %c
tùy chọn; bạn có thể sử dụng stat -t -- "$file" | awk '{print $8}'
nhưng điều này chỉ hoạt động nếu tên tệp không chứa khoảng trắng hoặc stat -t -- "$file" | awk 'END {print $(NF-8)}'
đối phó với tên tệp tùy ý nhưng không có các trường bổ sung trong tương lai vào stat
đầu ra.stat
tiện ích khác nhau đòi hỏi stat -f %d -- "$file"
.stat
tiện ích.Nếu Perl có sẵn, bạn có thể sử dụng
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
và để làm so sánh:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Lưu ý rằng có một số trường hợp góc mà kết quả mong muốn không rõ ràng. Ví dụ, với gắn kết ràng buộc Linux, sau mount --bind /foo /bar
, /foo
và /bar
được coi là hệ thống tập tin tương tự. Luôn có khả năng hai tệp thực sự nằm trên cùng một thiết bị nhưng bạn sẽ không bao giờ biết: ví dụ: nếu các tệp nằm trên hai giá treo mạng khác nhau, máy khách không có cách nào để biết liệu máy chủ có xuất các hệ thống tệp khác nhau hay không.
Nếu các tệp là thư mục và bạn có thể ghi vào chúng, một phương pháp khác là tạo một tệp tạm thời và cố gắng tạo một liên kết cứng. Điều này báo cáo một kết quả tiêu cực trên các liên kết gắn kết Linux.
tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"
df
không phải lúc nào cũng cung cấp tên thiết bị, nhưng đôi khi một liên kết tượng trưng đến nó như /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
làm cho df
không đáng tin cậy. Tùy chọn đáng tin cậy duy nhất cho đến nay là sử dụng stat
giải pháp dựa trên cơ sở.
df
báo cáo cho thiết bị, nó phù hợp giữa hai cách gọi, vì vậy việc so sánh là được.
df
báo cáo duy nhất /dev/sda6
và /dev/disk/by-uuid/ca09b...
, cả hai đều đề cập đến cùng một thiết bị, nhưng các điểm gắn kết khác nhau. Kiểm tra so sánh chuỗi rõ ràng thất bại khi thử với các tệp từ mỗi điểm gắn kết.
mount /dev/sda6 /mnt1
tiếp theo là các mount /dev/sda6 /mnt2
tác phẩm như một bùa mê. cat /proc/mounts
là tốt với nó Tuy nhiên, chỉ vì Wheezy /dev/disk/by-uuid/ca09b...
được hiển thị df
dưới dạng thiết bị cho hệ thống tập tin gốc. Nỗ lực hơn nữa để gắn kết nó bằng cách sử simlink này hoặc UUID=ca09b...
gắn cú pháp không kết thúc cho thấy bất cứ điều gì khác hơn /dev/sda6
trong df
(Tôi không biết làm thế nào để tái tạo những gì nó thực hiện trong suốt quá trình khởi động, nhưng đó không phải là mối quan tâm ở đây).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Hoạt động với bất kỳ số lượng đường dẫn.
df
là không luôn luôn là một ý tưởng tốt .
$6
), không phải tên thiết bị ( $1
), vì vậy đó không phải là vấn đề.
Giải pháp hoàn hảo nhất có sẵn trong POSIX là so sánh ID thiết bị của các tệp được cung cấp bởi chức năng stat (2) .
Perl có chức năng thống kê tương tự như Gilles đã chỉ ra :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
nhưng "cách POSIX" là sử dụng chương trình C như:
./checksamedev file1 file2
mã nguồn nào như sau:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct stat s1, s2;
if( argc==3 && lstat(argv[1], &s1)==0 && lstat(argv[2], &s2)==0 )
return !(s1.st_dev == s2.st_dev);
return 2;
}
Nếu ID thiết bị của cả hai tệp bằng nhau, chúng được lưu trữ trên cùng một hệ thống tệp, trong trường hợp đó, các lệnh trên trả về 0 (giá trị khác). Kiểm tra với echo $?
.
Điều này hoạt động tốt với các liên kết gắn kết, nhưng có lẽ sẽ không với các kết nối mạng.