Comment puis-je vérifier si se /my/dir
trouve sur la même partition que /
?
C'est pour l'intégration dans un script. Les montures de liaison doivent être manipulées correctement. Les solutions compatibles POSIX sont les bienvenues.
Comment puis-je vérifier si se /my/dir
trouve sur la même partition que /
?
C'est pour l'intégration dans un script. Les montures de liaison doivent être manipulées correctement. Les solutions compatibles POSIX sont les bienvenues.
Réponses:
Vous pouvez vérifier cela avec stat:
$ stat -c '%d %m' /proc/sys/
3 /proc
Vous indique le numéro de périphérique et l'endroit où votre répertoire a été monté.
stat
commande shell n'est pas POSIX ...
La commande suivante donne un nom unique au point de montage contenant le fichier $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Cela fonctionne sur n'importe quel système POSIX . L' -P
option impose un format prévisible; le premier champ de la deuxième ligne est le «nom du système de fichiers». Ainsi, pour vérifier que deux fichiers se trouvent sous le même point de montage:
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
Ou, pour enregistrer quelques appels de processus:
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
Quelques systèmes d'exploitation peuvent avoir des espaces dans les noms de volume. Il n'y a aucun moyen complètement fiable d'analyser la df
sortie dans ce cas.
Sous le capot, vous pouvez identifier le système de fichiers contenant un fichier par le st_dev
champ renvoyé par stat
. Il n'y a aucun moyen portable de le faire à partir d'un script shell. Certains systèmes ont un stat
utilitaire, mais sa syntaxe varie:
stat
signale le st_dev
champ lorsqu'il est appelé en tant que stat -c %D -- "$file"
.stat
qui est compatible avec GNU coreutils. D'autres ont stat
sans %c
option; vous pouvez utiliser, stat -t -- "$file" | awk '{print $8}'
mais cela ne fonctionne que si le nom de fichier ne contient pas d'espaces, ou stat -t -- "$file" | awk 'END {print $(NF-8)}'
qui accepte des noms de fichiers arbitraires mais pas avec de futurs ajouts de champs à la stat
sortie.stat
utilitaire différent qui nécessite stat -f %d -- "$file"
.stat
utilitaire.Si Perl est disponible, vous pouvez utiliser
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
et pour faire la comparaison:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Notez qu'il existe des cas d'angle où le résultat souhaité n'est pas clair. Par exemple, avec pochettes de protection se lient de Linux, après mount --bind /foo /bar
, /foo
et /bar
sont considérés comme le même système de fichiers. Il est toujours possible que les deux fichiers se trouvent réellement sur le même appareil, mais vous ne le saurez jamais: par exemple, si les fichiers se trouvent sur deux montages réseau différents, le client n'a aucun moyen de savoir si le serveur exporte des systèmes de fichiers différents.
Si les fichiers sont des répertoires et que vous pouvez y écrire, une autre méthode consiste à créer un fichier temporaire et à tenter de créer un lien dur. Celui-ci signale un résultat négatif sur les montages de liaison 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
ne donne pas toujours le nom de l'appareil, mais parfois un lien symbolique vers celui-ci, comme /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
rendre df
non fiable. Jusqu'à présent, la seule option fiable consiste à utiliser une stat
solution basée sur.
df
signalé pour le périphérique, il est cohérent entre les deux invocations, donc c'est correct pour une comparaison.
df
rapport /dev/sda6
et /dev/disk/by-uuid/ca09b...
, tous deux faisant référence au même périphérique, mais à des points de montage différents. Le test de comparaison de chaînes échoue évidemment lors de la tentative avec des fichiers de chaque point de montage.
mount /dev/sda6 /mnt1
suivi par des mount /dev/sda6 /mnt2
œuvres comme un charme. cat /proc/mounts
est bien avec ça. Cependant, ce n'est que depuis Wheezy qui /dev/disk/by-uuid/ca09b...
est affiché en df
tant que périphérique pour le système de fichiers racine. D'autres tentatives de montage à l'aide de ce lien sim ou de la UUID=ca09b...
syntaxe de montage ne finissent par afficher autre chose que /dev/sda6
dans df
(je ne sais pas comment reproduire ce qu'il a fait pendant le processus de démarrage, mais ce n'est pas le problème ici).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Fonctionne avec un nombre illimité de chemins.
df
n'est pas toujours une bonne idée .
$6
), pas le nom du périphérique ( $1
), donc cela ne devrait pas être un problème.
La meilleure solution infaillible disponible dans POSIX est la comparaison des ID de périphérique des fichiers fournis par la fonction stat (2) .
Perl a une même fonction stat que Gilles a fait remarquer :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
mais la "façon POSIX" consiste à utiliser un programme C comme:
./checksamedev file1 file2
dont le code source est le suivant:
#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;
}
Si les ID de périphérique des deux fichiers sont égaux, ils sont hébergés sur le même système de fichiers, auquel cas, les commandes ci-dessus renvoient 0 (une autre valeur sinon). Vérifiez avec echo $?
.
Cela fonctionne bien avec les montages de liaison, mais probablement pas avec les montages réseau.