Як я можу перевірити, чи /my/dir
є на тому ж розділі, що і /
?
Це для інтеграції в сценарій. Кріплення кріплення слід поводитись правильно. Рішення, сумісні з POSIX, вітаються.
Як я можу перевірити, чи /my/dir
є на тому ж розділі, що і /
?
Це для інтеграції в сценарій. Кріплення кріплення слід поводитись правильно. Рішення, сумісні з POSIX, вітаються.
Відповіді:
Ви можете перевірити це за допомогою stat:
$ stat -c '%d %m' /proc/sys/
3 /proc
Показує номер пристрою та місце монтажу вашого каталогу.
stat
оболонки не POSIX ...
Наступна команда дає унікальне ім'я для точки монтування, що містить файл $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Це працює в будь-якій системі POSIX . -P
Варіант передбачає передбачуваний формат; перше поле другого рядка - "ім'я файлової системи". Таким чином, для перевірки два файли знаходяться в одній точці монтажу:
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
Або зберегти пару викликів процесу:
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
Кілька операційних систем можуть мати пробіли в назвах томів. У df
цьому випадку немає повністю надійного способу розбору результатів.
Під капотом ви можете ідентифікувати файлову систему, що містить файл, по st_dev
поверненому полі stat
. Немає портативного способу зробити це із скрипту оболонки. Деякі системи мають stat
утиліту, але її синтаксис змінюється:
stat
повідомляє st_dev
поле, коли викликається як stat -c %D -- "$file"
.stat
сумісний з основними програмами GNU. Інші - stat
без %c
вибору; Ви можете використовувати, stat -t -- "$file" | awk '{print $8}'
але це працює лише в тому випадку, якщо ім'я файлу не містить пробілів, або stat -t -- "$file" | awk 'END {print $(NF-8)}'
яке справляється з довільними іменами файлів, але не з майбутніми доповненнями полів до stat
виводу.stat
корисність, яка вимагає stat -f %d -- "$file"
.stat
корисності.Якщо Perl доступний, ви можете використовувати
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
і зробити порівняння:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Зауважте, що є деякі кутові випадки, коли бажаний результат не зрозумілий. Наприклад, з прив'язкою кріплень Linux після mount --bind /foo /bar
, /foo
і /bar
вважаються тією ж файловою системою. Завжди можливо, що два файли фактично розташовані на одному пристрої, але ви ніколи не дізнаєтесь: наприклад, якщо файли знаходяться на двох різних мережевих кріпленнях, клієнт не може знати, чи сервер експортує різні файлові системи.
Якщо файли - це каталоги, і ви можете писати в них, інший спосіб - це створити тимчасовий файл і спробувати зробити жорстке посилання. Цей звіт повідомляє про негативний результат у всіх кріпленнях 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
не завжди дає ім’я пристрою, але колись це посилання на нього, як /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
зробити df
не надійним. Єдиним надійним варіантом поки що є використання stat
базованого рішення.
df
повідомляється для пристрою, воно відповідає двом викликам, тому для порівняння це нормально.
df
звіт /dev/sda6
і /dev/disk/by-uuid/ca09b...
обидва посилання на один і той же пристрій, але різні точки монтажу. Тест порівняння рядків, очевидно, не вдається при спробі з файлами з кожної точки монтажу.
mount /dev/sda6 /mnt1
слідом за mount /dev/sda6 /mnt2
роботами, як зачарування. cat /proc/mounts
добре з цим. Однак це лише з Wheezy, що /dev/disk/by-uuid/ca09b...
показано в df
якості пристрою для кореневої файлової системи. Подальші спроби встановити його за допомогою цього simlink або UUID=ca09b...
синтаксису mount не закінчуються показанням нічого іншого, ніж /dev/sda6
у df
(я не знаю, як відтворити те, що було зроблено під час завантажувального процесу, але це тут не викликає занепокоєння).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Працює з будь-якою кількістю шляхів.
df
є не завжди хорошою ідеєю .
$6
), а не назву пристрою ( $1
), так що це не повинно бути проблемою.
Найкраще безпроблемне рішення, доступне в POSIX, - це порівняння ідентифікаторів пристрою файлів, наданих функцією stat (2) .
Perl має аналогічну функцію стат , як Жиль зазначив :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
але "спосіб POSIX" полягає у використанні програми на зразок C:
./checksamedev file1 file2
який вихідний код такий:
#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;
}
Якщо ідентифікатори обох файлів рівні, вони розміщуються в одній файловій системі, і в цьому випадку команди вище повертають 0 (інше значення - інакше). Перевірте echo $?
.
Це добре працює з прив'язними кріпленнями, але, ймовірно, не буде з мережевими кріпленнями.