So erhalten Sie den Einhängepunkt des Dateisystems, das die angegebene Datei enthält

12

Ich suche nach einer schnellen Möglichkeit, den Einhängepunkt des Dateisystems zu finden, das eine bestimmte DATEI enthält. Gibt es etwas Einfacheres oder Direkteres als meine unten stehende Lösung?

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

Eine ähnliche Frage " Gibt es einen Befehl, um zu sehen, wo eine Festplatte bereitgestellt ist? " Verwendet den Geräteknoten der aktuellen Festplatte als Eingabe und keine beliebige Datei von der Festplatte ...

Stu
quelle
1
Sie können den letzten trAnruf awk -F'% '...
Joseph R.

Antworten:

6

Sie könnten so etwas tun

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

oder auch

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

Da das awkAufteilen von Leerzeichen standardmäßig erfolgt, müssen Sie das nicht angeben -Fund das Leerzeichen auch nicht mit trimmen tr. Schließlich können Sie durch Angabe der interessierenden Zeilennummer ( NR==2) auch darauf verzichten tail.

terdon
quelle
Die 2. Beschwörung funktionierte sofort, während ich in der ersten 2 auf 3 ändern musste. ordentlich
Stu
@ Gilles, danke für die Bearbeitung. Eine Frage, die zweite sollte auch ohne -Prichtig funktionieren ? In allen Fällen sollte das allerletzte Feld, von dem gedruckt wird awk, die Festplatte sein.
Terdon
@Stu das liegt wahrscheinlich daran, dass ich die -POption, die Gilles gerade hinzugefügt hat, nicht verwendet habe .
Terdon
1
@terdon Ja, in der Tat ist das letzte Feld der letzten Zeile das gleiche ohne -P. Trotzdem empfehle ich, immer zu verwenden, -Pwenn Sie die Ausgabe von analysieren df. Es ist einfacher, als zu überprüfen, ob diese bestimmte Verwendung sicher ist.
Gilles 'SO - hör auf böse zu sein'
nett. Wenn Sie jetzt den / dev-Eintrag für $ {FILE} benötigen (aus irgendeinem Grund)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
synchronisiert
15

Wenn Sie unter GNU / Linux GNU stataus Coreutils 8.6 oder höher haben, können Sie Folgendes tun:

stat -c %m -- "$file"

Andernfalls:

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

Ihr Ansatz ist gültig, setzt jedoch voraus, dass der Einhängepunkt kein Leerzeichen,%, Zeilenumbruch oder andere nicht druckbare Zeichen enthält. Sie können ihn mit neueren Versionen von GNU df(8.21 oder höher) geringfügig vereinfachen :

df --output=target FILE | tail -n +2
Stéphane Chazelas
quelle
Mein dferkennt die --outputOption nicht.
Joseph R.
@ JosephR. ist es Version 8.21 oder höher?
Terdon
@terdon Nein, es ist Version 8.13.
Joseph R.
2
@ JosephR. Stephane erklärt in seiner Antwort, dass dies ein Merkmal von GNU df> = 8.21 ist.
Terdon
@terdon Sorry muss es beim Überfliegen verpasst haben.
Joseph R.
7

Für Linux haben wir findmnt von util-linux genau dafür gemacht

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

Beachten Sie, dass eine Art zufälliger Mountpunkt zurückgegeben werden kann, falls mehrere Bindungs-Mounts vorhanden sind. Die Verwendung dfhat das gleiche Problem.

rudimeier
quelle
2
Funktioniert auch mit den Dateien, die sich in Subvolumes befinden, ordnungsgemäß.
Zeremonie
3

Da statein "Gerät" -Feld zurückgegeben wird, war ich gespannt, wie der zugrunde liegende stat()Bibliotheksaufruf verwendet werden kann, um diese Informationen programmgesteuert auf POSIX-kompatible Weise abzurufen.

Dieser Ausschnitt aus C-Code:

#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;
}  

Gibt die Haupt- und Nebengeräte-IDs für das Gerät an, das die in der Befehlszeile ( argv[1]) aufgeführte Datei enthält . Leider major()und minor()nicht POSIX, obwohl die Manpage behauptet, dass sie neben GNU / Linux "auf vielen anderen Systemen vorhanden" sind.

Sie können dann eine Korrespondenz zwischen der Haupt- / Nebennummer des Geräts und dem Geräteknoten von z. B. /proc/diskstatsabrufen und diese zuordnen, um Punkte von /proc/mounts, auch bekannt als, anzuhängen. /etc/mtab.

Ein Befehlszeilenprogramm, um dies zu tun, wäre also ziemlich einfach.

Goldlöckchen
quelle
/proc/diskstatsist nur für Block-Geräte, Sie werden die NFS, Proc, Fuse vermissen ... Zumindest unter Linux können verschiedene Mountpoints die gleiche Maj + Min haben
Stéphane Chazelas
Wusste das nicht, danke. Es scheint auch, dass dies st_devmöglicherweise keine Möglichkeit bietet, eine NFS-Partition von einer anderen zu unterscheiden. Wer dies tatsächlich schreiben will, muss dies berücksichtigen;)
Goldlöckchen
+1 für genug Geek, dass Sie C-Code "einfacher oder direkter" schreiben als das, was das OP tat :).
Terdon
0

Hier ist mehr C ++ - Code, wenn Sie dies von C ++ aus tun möchten ...

  #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();
  }

Weitere Links für programmatische Möglichkeiten

Mark Lakata
quelle