List Volumes with DF, Grep, Awk | Bash Shell

930 views Asked by At

Trying to print all entries which start with /Volumes/, this to list mounted volumes on mac. See Updates.

IFS=$'\n' read -r -d '' -a volumes < <(
  df  | egrep -o '/Volumes/.*'
)

echo "${volumes}"

Update 1: This worked, but prints a space before each new line.

#!/usr/bin/env bash


IFS=$'\n' read -r -d '' -a volumes < <(
  df | egrep -oi '(\s+/Volumes/\S+)'
)

printf "%s\n" "${volumes[@]}"

Update 2: Worked, but doesn't print volume names with spaces in it

IFS=$'\n' read -d '' -ra volumes < <(
df | awk 'index($NF, "/Volumes/")==1 { print $NF }'
)

printf '%s\n' ${volumes[@]}

Update 3: Prints the second part of the volume name with spaces in it on a new line

IFS=$'\n' read -d '' -ra volumes < <(
df | awk -F ' {2,}' 'index($NF, "/Volumes/")==1 { print $NF }'
)

printf '%s\n' ${volumes[@]}

Solution:

Tested Platform: macOS Catalina

IFS=$'\n' read -d '' -ra volumes < <(
df | sed -En 's~.* (/Volumes/.+)$~\1~p'
)

printf '%s\n' "${volumes[@]}"

DF Output

Filesystem    512-blocks       Used  Available Capacity iused       ifree %iused  Mounted on
/dev/disk1s5   976490576   21517232  529729936     4%  484332  4881968548    0%   /
devfs                781        781          0   100%    1352           0  100%   /dev
/dev/disk1s1   976490576  413251888  529729936    44%  576448  4881876432    0%   /System/Volumes/Data
/dev/disk1s4   976490576   10487872  529729936     2%       6  4882452874    0%   /private/var/vm
map auto_home          0          0          0   100%       0           0  100%   /System/Volumes/Data/home
/dev/disk7s1       40880       5760      35120    15%     186  4294967093    0%   /private/tmp/tnt12079/mount
/dev/disk8s1       21448       1560      19888     8%       7  4294967272    0%   /Volumes/usb drive
/dev/disk6s1  9766926680 8646662552 1119135456    89%   18530 48834614870    0%   /Volumes/root
/dev/disk2s1    60425344   26823168   33602176    45%  419112      525034   44%   /Volumes/KINGS TON
3

There are 3 answers

9
anubhava On BEST ANSWER

You may use this pipeline in OSX:

IFS=$'\n' read -d '' -ra volumes < <(
df | sed -En 's~.* (/Volumes/.+)$~\1~p'
)

Check array content:

printf '%s\n' "${volumes[@]}"

or

declare -p volumes

declare -a volumes=([0]="/Volumes/Recovery" [1]="/Volumes/Preboot")
5
Wiktor Stribiżew On

You may use

IFS=$'\n' read -r -d '' -a volumes < <(
  df -h | awk 'NR>1 && $6 ~ /^\/Volumes\//{print $6}'
)
printf "%s\n" "${volumes[@]}"

The awk command gets all lines other than the first one (NR>1) and where Field 6 ("Mounted on") starts with /Volumes/ (see $6 ~ /^\/Volumes\/), and then prints the Field 6 value.

The printf "%s\n" "${volumes[@]}" command will print all the items in the volumes array on separate lines.

If the volume paths happen to contain spaces, you may check if there is a digit followed with % followed with whitespaces and /Volume/ and then get join the fields starting with Field 6 with a space:

df -h | awk 'NR>1 && $0 ~ /[0-9]%[ \t]+\/Volumes\//{for (i=6;i<=NF;i++) {a=a" "$i}; print a}'
0
David C. Rankin On

It's a little unclear just what output you want, but you can always use awk to parse the information. For example if you want the "Filesytem" and "Mounted on" information, you can use with df:

df | awk '{
    for (i=1; i<=NF; i++)
        if ($i ~ /^\/Volumes/) {
            print $1, substr($0, match($0,/\/Volumes/))
            break
        }
    }'

Or using the input you provided in the file dfout, you could read the file as:

awk '{
    for (i=1; i<=NF; i++)
        if ($i ~ /^\/Volumes/) {
            print $1, substr($0, print $1, substr($0, match($0,/\/Volumes/)))
            break
        }
}' dfout

Example Output

Using the file dfout with your data you would receive:

/dev/disk8s1 /Volumes/usb drive
/dev/disk6s1 /Volumes/root
/dev/disk2s1 /Volumes/KINGS TON

If you need more or less of each record, you can just output whatever other fields you like in the print statement.

Let me know if you want the format or output different and I'm happy to help further. I don't have a Mac to test on, but the functions uses are standard awk and not GNU awk specific.