Как найти, на каком устройстве находится файл (и использовать его в скрипте)?

Я хочу узнать, на каком устройстве находится мой файл, чтобы я мог использовать его в скрипте. Я могу зайти так далеко:

$ df . Filesystem 512-blocks Used Available Capacity Mounted on /dev/disk0s2 498438976 294369520 203557456 60% / 

но этот результат кажется слишком неуклюжим; есть ли лучший способ, чем разбор этого, чтобы получить первое «слово» второй строки?

Мне действительно нужно что-то подобное, поэтому я могу передать его следующей команде:

 $ somecommand . /dev/disk0s2 

Как я могу достичь этого, желательно, не прибегая к строковому взлому вывода «df»?

  • Удалите первый и последний символы, если они есть
  • Как написать sed однострочный, чтобы добавить символ после каждого третьего символа?
  • Shellscript для удаления определенных тегов в файле HTML
  • Как заменить строку в файле?
  • awk или sed или perl: удалять только символы в определенном месте
  • нужно понимать использование «/» в команде sed
  • Как найти минимальный столбец в каждом n-м интервале файла, используя sed, sort, tail?
  • Получите строку и поместите ее в начале строки, пока не будет найдена следующая строка
  • 5 Solutions collect form web for “Как найти, на каком устройстве находится файл (и использовать его в скрипте)?”

    Вы можете сделать это только с оболочкой (работает в bash , dash , ksh , zsh ):

     df . | (read a; read ab; echo "$a") 

    Или если вывод не нужен (результат будет храниться в $ a), и ваша оболочка поддерживает замену процесса (например, bash , zsh ):

     { read; read ab;}< <(df .) 

    И вот некоторые сравнения с скоростью других решений:

     # pure shell solution 1 bash-4.2$ time for i in $(seq 500); do df . | (read a; read ab; echo "$a"); done > /dev/null 1.899 (dash) $ time -f '%e' dash -c 'for i in $(seq 500); do df . | (read a; read ab; echo "$a"); done > /dev/null' 1.05 (ksh) $ time for i in $(seq 500); do df . | (read a; read ab; echo "$a"); done > /dev/null 0m1.16s real 0m0.02s user 0m0.12s system (zsh) manatwork% time (for i in $(seq 500); do df . | (read a; read ab; echo "$a"); done > /dev/null) 1.51s # pure shell solution 2 bash-4.2$ time for i in $(seq 500); do { read; read ab;}< <(df .); done 1.192 (zsh) manatwork% time (for i in $(seq 500); do { read; read ab;}< <(df .); done) 3.51s # other solutions bash-4.2$ time for i in $(seq 500); do df . | tail -1 | cut -f 1 -d " "; done > /dev/null 1.405 bash-4.2$ time for i in $(seq 500); do df . | sed '2!d' | awk '{print $1}'; done > /dev/null 5.407 bash-4.2$ time for i in $(seq 500); do df . | sed -n '2{s/ .*$//;p}'; done > /dev/null 1.767 bash-4.2$ time for i in $(seq 500); do df . | sed '2!d' | awk '{print $1}'; done > /dev/null 3.334 bash-4.2$ time for i in $(seq 500); do df . | gawk 'NR==2{print $1}'; done > /dev/null 3.013 bash-4.2$ time for i in $(seq 500); do df . | mawk 'NR==2{print $1}'; done > /dev/null 1.747 bash-4.2$ time for i in $(seq 500); do df . | perl -nae 'print$F[0]if$.==2'; done > /dev/null 2.752 

    (Не сравнивается с решением stat поскольку он здесь не работает.)

    В UNIX это обычный способ объединить полномочия простых программ, которые нужно немного. Поэтому не беспокойтесь о том, чтобы вывести выход df через некоторый фильтр.

     df /path/to/file | sed -n '2{s/ .*$//;p}' 

    -n автоматически подавляет линии печати, 2{} выполняет закрытые команды во второй строке, s/ .*$// отбрасывает все из первого места, p печатает оставшиеся. Добавление q после p в случаях, когда один анализирует более длинный ввод и просто хочет, чтобы вторая (или n-я) строка также могла ускорить ее.

    Вы можете использовать простую однострочную линию с sed , awk как

     df . | sed '2!d' | awk '{print $1}' 

    В sed , указав 2d удалите вторую строку. Добавление ! отрицайте это, поэтому он просто удаляет все остальные строки и печатает вторую строку. Затем команда awk отображает первое значение столбца.

    Вывод:

     /dev/disk0s2 

    Анализ вывода df – это лучшее, что вы можете сделать портативно. Pass -P в df чтобы избежать форматирования вывода странным образом (вы, вероятно, безопасны везде, так как вы захватываете первое поле, но вам нужно -P захватить точку монтирования, поскольку она может быть отнесена к следующему если предыдущие столбцы слишком широкие).

     device_name=$(df -P . | awk 'NR==2 {print $1}') 

    Обратите внимание, что некоторые системы позволяют именам устройств содержать пробелы (IIRC, которые, как правило, происходят в OSX). Там нет портативного или удобного способа обработки этого случая.

    Я не думаю, что есть лучший способ сделать это под Linux. stat может предоставить вам номер устройства ( stat -c %t . ), но если вы хотите запись устройства в /dev , вы должны извлечь его из /proc , что лучше делать df .

    Если вы используете linux, вы можете сделать это с помощью findmnt (часть util-linux ) ", не прибегая к хакерству строк" :

     findmnt -no source -T /path/to/file 
      / DEV / sda1 

    При использовании опции

      -T, --target path 

    если путь не является файлом или каталогом mountpoint, findmnt проверяет элементы пути в обратном порядке, чтобы получить точку монтирования. Остальные две опции подавляют строку заголовка: -n, --noheading и выбирают столбцы (столбцы), которые должны быть перечислены: -o, --output


    df от coreutils имеет аналогичную опцию --output= печатать только определенные поля, например, source :

     df --output=source /path/to/file 
      Файловая система
     / DEV / sda1 

    однако нет возможности удалить заголовок. Если это проблема, вам придется выполнить минимальный взлом строки, например, подключить его к sed 1d

    Linux и Unix - лучшая ОС в мире.