Как получить точку монтирования файловой системы, содержащей данный файл

13

Я ищу быстрый способ найти точку монтирования файловой системы, содержащей данный файл. Есть ли что-нибудь более простое или прямое, чем мое решение ниже?

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

Аналогичный вопрос « Есть ли команда, чтобы увидеть, где смонтирован диск? » Использует узел устройства текущего диска в качестве входных данных, а не произвольный файл с диска ...

Stu
источник
1
Вы можете покончить с последним trзвонком с помощьюawk -F'% '...
Джозеф Р.

Ответы:

6

Вы могли бы сделать что-то вроде

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

или даже

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

Так как awkпо умолчанию разделяются на пробелы, вам не нужно указывать, -Fи вам также не нужно обрезать пробелы tr. Наконец, указав номер строки интереса ( NR==2), вы также можете покончить с tail.

Тердон
источник
2-е заклинание работало «из коробки», а мне пришлось сменить 2 на 3 в первом. опрятный
Stu
@ Жиль, спасибо за редактирование. Один вопрос, второй должен работать даже без -Pправа? Во всех случаях самое последнее поле, которое awkдолжно быть напечатано, должно быть диском.
Тердон
@Stu это, вероятно, потому что я не использовал -Pвариант, который только что добавил Жиль.
Тердон
1
@terdon Да, действительно, последнее поле последней строки то же самое без -P. Тем не менее, я рекомендую всегда использовать, -Pкогда вы анализируете вывод df, это проще, чем проверять, безопасно ли это конкретное использование.
Жиль "ТАК - перестань быть злым"
красивый. если вам нужно теперь / dev запись для $ {FILE} (по какой-то причине)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
несинхронизировано
16

В GNU / Linux, если у вас есть GNU statиз coreutils 8.6 или выше, вы можете сделать:

stat -c %m -- "$file"

В противном случае:

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

Ваш подход верен, но предполагает, что точка монтирования не содержит пробела,%, новой строки или других непечатаемых символов, вы можете немного упростить его с более новыми версиями GNU df(8.21 или выше):

df --output=target FILE | tail -n +2
Стефан Шазелас
источник
Мой dfне распознает --outputвариант.
Джозеф Р.
@JosephR. это версия 8.21 или выше?
Тердон
@terdon Нет, это версия 8.13.
Джозеф Р.
2
@JosephR. Стефан объясняет в своем ответе, что это особенность GNU df> = 8.21.
Тердон
@terdon Извините, наверное, пропустил это во время скимминга.
Джозеф Р.
8

Для Linux у нас есть findmnt из util-linux, специально созданный для этого

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

Обратите внимание, что какая-то произвольная точка монтирования может быть возвращена в случае, если есть несколько монтирований связывания. Использование dfимеет ту же проблему.

rudimeier
источник
2
Работает правильно даже с файлами, которые находятся в подразделах.
ceremcem
3

Так как statвозвращает поле «Device», мне было любопытно посмотреть, как можно использовать базовый stat()библиотечный вызов для программного получения этой информации POSIX-совместимым способом.

Этот фрагмент кода 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;
}  

Предоставит идентификаторы основных и вспомогательных устройств для устройства, содержащего файл, указанный в командной строке ( argv[1]). К сожалению, major()и minor()не POSIX, хотя на странице руководства утверждается, что они «присутствуют во многих других системах», кроме GNU / linux.

Затем вы можете получить соответствие между основным / второстепенным номером устройства и, например, узлом устройства /proc/diskstats, и сопоставить его с точками монтирования /proc/mounts, иначе. /etc/mtab,

Так что утилита командной строки сделать это будет довольно просто.

лютик золотистый
источник
/proc/diskstatsтолько для блочных устройств, вы пропустите NFS, proc, fuse ... По крайней мере, в Linux разные точки монтирования могут иметь одинаковые значения maj + min
Стефан Шазелас
Не знал, что, спасибо. Также кажется, что st_devможет не обеспечить способ отличить один раздел NFS от другого. Тот, кто действительно хочет написать это, должен принять это во внимание;)
Златовласка
+1 за то, что достаточно выродка, которого вы считаете написанием кода на C "более простым или более прямым", чем то, что делал OP :).
Тердон
0

Вот еще код C ++, если вы хотите сделать это из 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();
  }

Больше ссылок для программных способов

Марк Лаката
источник