Как я могу получить вывод df -Th для вывода определенного значения столбца в сценарии bash? - PullRequest
0 голосов
/ 12 января 2020

Я получил вывод df -Th в файл test.dat. Есть ли способ, которым мы могли бы получить конкретное значение из df -Th в конкретном c слове, таком как /dev/xvda is mounted on /dev and has file system type tmpfs

Я пробовал следующее, но не смог выяснить полностью.

#!/bin/bash
df -Th
df -Th > test.dat
filename="test.dat"
sed 1d $filename | while IFS=, read -r filesystem Type mountedOn
do
echo "$filesystem is mounted on $mountedOn and file system type is $Type\n"
done < $filename

Вывод df -Th:

Filesystem     Type      Size  Used Avail Use% Mounted on
udev           devtmpfs  7.7G     0  7.7G   0% /dev
tmpfs          tmpfs     1.6G  2.2M  1.6G   1% /run
/dev/nvme0n1p2 ext4      916G   81G  789G  10% /
tmpfs          tmpfs     7.7G  441M  7.3G   6% /dev/shm

Спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 13 января 2020

По крайней мере одна из строк, которые вы пытаетесь извлечь, может содержать пустые символы - это, вероятно, необычно, но ничто не мешает точке монтирования иметь пробелы на своем пути. Следовательно, анализ df может работать не так, как ожидалось.

Учитывая, что вы находитесь на Linux, есть вероятность, что у вас есть df из Coreutils . Он должен содержать удобную опцию --output, которая позволяет указывать список полей для печати. ​​

#!/bin/bash

for dev in /dev/sd*; do
    printf '%s '  "$dev is mounted on"
    printf '%s '  "$(df --output=target "$dev" | tail -n +2)"
    printf '%s '  "and file system type is"
    printf '%s\n' "$(df --output=fstype "$dev" | tail -n +2)"
done

Конечно, это работает правильно только в предположении, что точки монтирования и типы файловой системы могут не иметь завершающие символы новой строки (которые могут быть удалены путем подстановки команд; однако это может быть обойдено вокруг ).
Кроме того, вывод будет включать нежелательные элементы, если вы не убедитесь, что все пути к устройствам /dev/sd* расширяется на самом деле установлены. Вы можете сделать это, например, добавив findmnt --source "$dev" 1>/dev/null || continue в качестве первой команды внутри l oop. findmnt предоставляется util- linux.

В качестве альтернативы, если у вас есть findmnt, его опция -r (необработанный формат вывода, все потенциально небезопасные символы - шестнадцатеричные можно использовать для обеспечения надежного синтаксического анализа его вывода:

findmnt -n -D -r -o source,target,fstype |
  awk '{ print $1,"is mounted on",$2,"and file system type is",$3 }'

С дополнительными преимуществами по сравнению с моим предыдущим предложением эффективности (только два вызова внешних инструментов) и защиты от изменений в точках монтирования, которые может происходить между последовательными df вызовами.
Другие используемые опции предназначены для удаления заголовков (-n), вывода mimi c df, необходимого для исключения псевдофайловых систем (-D), и выбрать / заказать поля для печати (-o).

0 голосов
/ 13 января 2020

Вот как я это сделаю.

while read -ra line; do
  [[ ${line[0]} == Filesystem ]] && continue
  printf '%-15s is mounted on:  %-15s and file system type is:  %s\n' "${line[0]}" ${line[-1]}" "${line[1]}"
done < <(df -T)

Очевидно, что расстояние между ними недостаточно надежное, но эй! : -)

В bash встроенное чтение имеет опцию -a и сохраняет выход строк в массиве. поэтому "$ {line [0]}" - это первое поле / столбец в этом случае (и так далее). Мы проверяем, является ли первое поле Файловой системой, и пропускаем ли эту строку, используя встроенное значение continue , затем обрабатываем оставшиеся строки. Наконец, у printf есть возможность форматирования, поэтому мы используем его. <() </strong> называется заменой процесса, и для чтения из него мы используем знак перенаправления <</strong>. см. man bash

PAGER='less +/^[[:space:]]*process\ substitution' man bash

для получения дополнительной информации о ProcSub.

0 голосов
/ 12 января 2020

У вас более трех полей, поэтому вам нужно указать больше имен полей для read; и поля не разделены запятыми, поэтому IFS=, здесь определенно не так. Кроме того, вы должны вообще избегать временных файлов; и если их нельзя избежать, вы не должны использовать имя файла stati c (потому что тогда вы не можете запустить два экземпляра вашего сценария параллельно, и, что более серьезно, предсказуемые имена файлов открывают возможности для атак по символическим ссылкам) .

Однако с Awk это намного естественнее.

df -Th |
awk 'NR>1 { print $1, "mounted on", $NF, "type", $2 }'
...