Comment obtenir le point de montage d'un système de fichiers contenant un fichier donné

13

Je cherche un moyen rapide de trouver le point de montage du système de fichiers contenant un FICHIER donné. Y a-t-il quelque chose de plus simple ou de plus direct que ma solution ci-dessous?

df -h FILE |tail -1 | awk -F% '{print $NF}' | tr -d ' '

Une question similaire " Existe-t-il une commande pour voir où un disque est monté? " Utilise le nœud de périphérique du disque actuel en entrée, et non un fichier arbitraire du disque ...

Stu
la source
1
Vous pouvez supprimer l' trappel final en utilisantawk -F'% '...
Joseph R.

Réponses:

6

Vous pourriez faire quelque chose comme

df -P FILE | awk 'NR==2{print $NF}'

ou même

df -P FILE | awk 'END{print $NF}'

Étant donné que les awkfractionnements sur les espaces par défaut, vous n'avez pas besoin de spécifier le -Fet vous n'avez pas non plus besoin de découper les espaces avec tr. Enfin, en spécifiant le numéro de ligne d'intérêt ( NR==2), vous pouvez également vous en débarrasser tail.

terdon
la source
la 2e incantation a fonctionné hors de la boîte, alors que je devais changer 2 à 3 dans le premier. soigné
Stu
@Gilles, merci pour la modification. Une question, la seconde devrait fonctionner même sans -Pdroit? Dans tous les cas, le tout dernier champ imprimé par awkdoit être le disque.
terdon
@Stu c'est probablement parce que je n'avais pas utilisé l' -Poption que Gilles vient d'ajouter.
terdon
1
@terdon Oui, en effet, le dernier champ de la dernière ligne est le même sans -P. Néanmoins, je recommande de toujours utiliser -Plorsque vous analysez la sortie de df, c'est plus facile que de vérifier que cette utilisation particulière est sûre.
Gilles 'SO- arrête d'être méchant'
agréable. si vous devez maintenant l'entrée / dev pour $ {FILE} (pour une raison quelconque)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
non synchronisé le
16

Sur GNU / Linux, si vous avez GNU statde coreutils 8.6 ou supérieur, vous pouvez faire:

stat -c %m -- "$file"

Autrement:

mount_point_of() {
  f=$(readlink -e -- "$1") &&
    until mountpoint -q -- "$f"; do
      f=${f%/*}; f=${f:-/}
    done &&
    printf '%s\n' "$f"
}

Votre approche est valide mais suppose que le point de montage ne contient pas d'espace, de%, de nouvelle ligne ou d'autres caractères non imprimables, vous pouvez le simplifier légèrement avec des versions plus récentes de GNU df(8.21 ou supérieur):

df --output=target FILE | tail -n +2
Stéphane Chazelas
la source
Mon dfne reconnaît pas l' --outputoption.
Joseph R.
@JosephR. est-ce la version 8.21 ou supérieure?
terdon
@terdon Non, c'est la version 8.13.
Joseph R.
2
@JosephR. Stéphane explique dans sa réponse qu'il s'agit d'une fonctionnalité de GNU df> = 8.21.
terdon
@terdon Désolé, vous devez l'avoir manqué lors de l'écrémage.
Joseph R.
8

Pour Linux, nous avons findmnt de util-linux exactement fait pour cela

findmnt -n -o TARGET --target /path/to/FILE

Notez qu'une sorte de point de montage aléatoire peut être retourné au cas où il y aurait plusieurs montages de liaison. L'utilisation dfa le même problème.

rudimeier
la source
2
Fonctionne correctement même avec les fichiers qui se trouvent dans des sous-volumes.
ceremcem
3

Étant donné que statrenvoie un champ "Device", j'étais curieux de voir comment l' stat()appel de bibliothèque sous-jacent pouvait être utilisé pour obtenir ces informations par programme de manière compatible POSIX.

Cet extrait de code C:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main (int argc, const char *argv[]) {
    struct stat info;
    stat(argv[1], &info);
    printf("min: %d maj: %d\n",
        minor(info.st_dev),
        major(info.st_dev)
    );

    return 0;
}  

Donnera les ID des périphériques majeurs et mineurs pour le périphérique contenant le fichier répertorié sur la ligne de commande ( argv[1]). Malheureusement, major()et minor()ne sont pas POSIX, bien que la page de manuel affirme qu'ils sont "présents sur de nombreux autres systèmes" en plus de GNU / linux.

Vous pouvez ensuite obtenir une correspondance entre le numéro majeur / mineur du périphérique et le nœud du périphérique, par exemple /proc/diskstats, et le mapper à partir duquel les points de montage /proc/mounts, aka. /etc/mtab.

Un utilitaire en ligne de commande pour ce faire serait donc assez simple.

boucle d'or
la source
/proc/diskstatsest uniquement pour les périphériques bloc, vous allez manquer le NFS, proc, fusible ... Sur Linux au moins, différents points de montage peuvent avoir le même maj + min
Stéphane Chazelas
Je ne savais pas ça, merci. Il semble également que st_devcela ne fournisse pas un moyen de distinguer une partition NFS d'une autre. Celui qui veut vraiment écrire ceci devra en tenir compte;)
goldilocks
+1 pour être assez geek que vous envisagez d'écrire du code C "plus simple ou plus direct" que ce que l'OP faisait :).
terdon
0

Voici plus de code C ++ si vous souhaitez le faire à partir de C ++ ...

  #include <boost/filesystem.hpp>
  #include <sys/stat.h>

  /// returns true if the path is a mount point
  bool Stat::IsMount(const std::string& path)
  {

      if (path == "") return false;
      if (path == "/") return true;

      boost::filesystem::path path2(path);
      auto parent = path2.parent_path();

      struct stat sb_path;
      if (lstat(path.c_str(), &sb_path) == -1) return false; // path does not exist
      if (!S_ISDIR(sb_path.st_mode)) return false; // path is not a directory

      struct stat sb_parent;
      if (lstat(parent.string().c_str(), &sb_parent) == -1 ) return false; // parent does not exist

      if (sb_path.st_dev == sb_parent.st_dev) return false; // parent and child have same device id

      return true;

  }

  /// returns the path to the mount point that contains the path
  std::string Stat::MountPoint(const std::string& path0)
  {
      // first find the first "real" part of the path, because this file may not exist yet
      boost::filesystem::path path(path0);
      while(!boost::filesystem::exists(path) )
      {
          path = path.parent_path();
      }

      // then look for the mount point
      path = boost::filesystem::canonical(path);
      while(! IsMount(path.string()) )
      {
          path = path.parent_path();
      }

      return path.string();
  }

Plus de liens pour les moyens programmatiques

Mark Lakata
la source