Dans * nix, comment déterminer sur quel système de fichiers se trouve un fichier particulier?

12

Dans un environnement générique et moderne Unix (par exemple, GNU / Linux, GNU / Solaris ou Mac OS X), existe-t-il un bon moyen de déterminer sur quel point de montage et type de système de fichiers se trouve un chemin de fichier absolu particulier?

Je suppose que je pourrais exécuter la mountcommande et analyser manuellement la sortie de cela et la comparer en chaîne avec mon chemin de fichier, mais avant de le faire, je me demande s'il existe une méthode plus élégante.

Je développe un script BASH qui utilise des attributs étendus et je veux en faire la bonne chose (dans la mesure du possible) pour une variété de systèmes de fichiers et d'environnements hôtes.

smokris
la source

Réponses:

19

La commande df(1)prend un ou plusieurs arguments et renvoie le point de montage et le périphérique sur lesquels ce fichier ou répertoire existe, ainsi que les informations d'utilisation. Vous pouvez ensuite utiliser le chemin ou le périphérique pour rechercher le type de système de fichiers dans la sortie de mount -vou similaire.

Malheureusement, le format de sortie des deux dfet mountdépend du système; il n'y a pas de norme apparente, du moins comme je peux le voir entre Solaris, NetBSD et Mac OS X.

Morven
la source
1
df -Pdevrait produire une sortie standardisée sur tout système compatible POSIX. Certains systèmes loufoques peuvent également nécessiter une variable d'environnement magique, telle que POSIXLY_CORRECT.
Dan Moulding
L'exemple df /path-to-the-directoryvous donnera la partition contenant de ce répertoire
Hasanuzzaman Sattar
7

Vous pouvez utiliser stat . La commande stat --printf '% d' filename.txt renverra le numéro de périphérique en hexadécimal / décimal.

Zoredache
la source
Alors, comment trouver la base du nom de l'appareil là-dessus?
daisy
Vous devez parcourir tous les fichiers de périphérique dans / dev / et en rechercher un avec le même numéro mineur que stat signalé.
Wiesław Herr
stat --printf "%d"vous indique le numéro mineur d'un périphérique, mais il reste du travail à faire pour obtenir le nom du périphérique et son système de fichiers monté.
Craig McQueen
2
Il s'agit peut-être d'un ajout récent, mais stat --format '%m' $fileil vous donnera le point de montage et stat --file-system --format '%T' $mountfournira le nom du type de système de fichiers.
roaima
1
@ TomHale: ne me souviens pas, pour être honnête. Mais je me souviens que cela n'a pas fonctionné. Certes, j'aurais dû indiquer la distribution, la version du noyau, etc. Si le résultat net est que cela fonctionne, tant
mieux
3

Pour un fichier spécifique, c'est aussi simple que

df -T "${FILE}" | awk '{print $2}' | tail -n1
Julian Pawlowski
la source
Ne fonctionne pas avec btrfs!
0xC0000022L
2

Hm. Pour le point de montage, vous pouvez remonter la hiérarchie jusqu'à ce que st_dev change (alors vous venez de franchir une limite de montage); il y a GNU statpour les scripts bash; cependant, je ne sais pas comment deviner le type de système de fichiers sans analyse /proc/mountsou par essais et erreurs (c.-à-d. gérer les échecs après avoir défini des attributs étendus)

ΤΖΩΤΖΙΟΥ
la source
2

Un problème avec l'utilisation dfest que si le nom du périphérique dans la sortie est long, sa ligne sera bouclée de sorte que vous ne pouvez pas simplement saisir la dernière ligne. À la place, supprimez la première ligne, puis saisissez la nouvelle première ligne, puis imprimez le premier champ:

#!/usr/bin/env bash

path=$1
curdir=$(pwd)
cd $path
df . | tail -n +2 | head -1 | awk '{print $1}'
cd $curdir
mage2k
la source
3
Évitez ce problème en utilisant 'df -P' pour obtenir une sortie au format POSIX et sans saut de ligne.
MikeyB
2

Il semble y avoir un problème avec df et btrfs sous Linux. Lorsque vous demandez à df de localiser le point de montage d'un volume btrfs monté, il fera la bonne chose. Dans ce cas, joe est un sous-répertoire de / m / whale / backup.

# df /srv/backup/joe
Filesystem      1K-blocks      Used  Available Use% Mounted on
/dev/md126     2930135488 307676684 2619663252  11% /m/whale/backup

Mais si le répertoire référencé est un sous-volume, il ne vous indiquera plus le point de montage.

# df /srv/backup/joe/code
Filesystem      1K-blocks      Used  Available Use% Mounted on
-              2930135488 307676684 2619663252  11% /a/whale/backup/joe/code

Le / a / whale / backup est le seul point de montage selon le noyau.

# mount | grep whale
/dev/md126 on /a/whale/backup type btrfs (rw,relatime,space_cache)

FWIW, stat fait la même chose:

# stat --printf '%m\n' /srv/backup/joe/code
/a/whale/backup/joe/code
Marc Singer
la source
1

Depuis /programming/2167558/give-the-mount-point-of-a-path :

 df -P $path  | tail -1 | awk '{ print $NF}'

fonctionne partout où j'ai testé, à la fois pour * BSD et sysVs, et pour les répertoires farfelus montés automatiquement. Je serais ravi d'entendre parler d'un cas où il échoue.

Charles Stewart
la source
1
Le code suggéré df -P $ path | queue -1 | awk '{print $ NF}' échoue sur toutes les versions de Solaris que j'ai essayées (2.5.1, 8, 9 et 10) car "df" de Solaris ne prend pas en charge l'option "-P".
Peter John Acklam
@Peter: Je suis moins ravi que je ne le pensais. Mais il est intéressant de savoir que le problème n'est pas anodin. Je pense que la bonne chose est d'écrire une commande dans un langage de script dont la bibliothèque a résolu le problème correctement, par exemple, Python a la fonction os.path.splitunc () qui donne le point de montage et que je suppose fonctionne sur Solaris.
Charles Stewart
@CharlesStewart: Malheureusement, il n'y a pas une telle fonction en Python à ma connaissance. os.path.splitunc()ne fonctionne que pour les chemins UNC et n'est disponible que sous Windows .
Aleksi Torhamo