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

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

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

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

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

 $ somecommand . /dev/disk0s2 

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

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

  • Создайте список каждого пользователя, которому принадлежит файл в заданном каталоге, а также количество файлов и каталогов, которыми они владеют.
  • (Mac Terminal) sed для анализа JSON ... что я делаю неправильно?
  • Цветной вывод меньше при обращении к файлу журнала
  • Как получить только имя файла с помощью sed
  • Как добавить дефисы в первую пустую строку текстового файла?
  • Почему * соответствует, где нет цифр?
  • Скрипт Sed / awk для нестандартного журнала доступа Apache (Oracle Weblogic)
  • Используйте sed для извлечения переменной из 1 файла и поместите ее в другую
  • Как удалить строку, если строка является единственной вещью на линии
  • Как сопоставить литерал '*' с sed?
  • sed + update /etc/grub.conf, несмотря на этот файл ссылки
  • Linux и Unix - лучшая ОС в мире.