Most references that I found while searching for a simple way to
find the device where a particular file is stored pointed to
the df
command. However, this does not work if the file is managed
by a 'virtual' file system type such as ecryptfs that
automatically encrypts its stored contents.
The bash script shown below shows how to do this:
me@pc :~$ df file.txt
Filesystem 1K-blocks Used Available Use% Mounted on
/home/me/.Private 237996696 173473232 52433916 77% /home/me
One solution could be to take the 'virtual' filesystem and
use df
to find its underlying file system etc. until a
'real' file system representing a storage device is found.
me@pc :~$ df /home/me/.Private
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 237996696 173473824 52433324 77% /
Another way is based on the full pathname of the file: simply
find the longest prefix of the file's pathname that corresponds
to a mounted device from /dev.
The bash script shown below shows how to do this:
- Use the readlink command to obtain the full 'canonical' pathname of the input file name.
- Select all /dev devices that are currently mounted
from /etc/mtab.
The second column of /etc/mtab, referenced as $2 in the
awk
program,
contains the mount point. Since the first character of a string is at
index 1 in awk (instead of 0, as in C), the test
(index(fnm, $2) == 1)
- After sort, the mount point that is the longest prefix is the last line of the output, selected using the tail command into the $mpoint variable.
- It only remains to retrieve the device mounted on $mpoint by selecting appropriately from /etc/mtab.
#!/bin/bash
readonly USAGE="devof file"
function fatal() {
echo "$1" 2>&1; exit 1
}
[[ $# == 1 ]] || fatal "usage: $USAGE"
[[ -e "$1" ]] || fatal "'$1' not a file";
# readlink -f: follow symbolic links
path=$(readlink -f "$1")
# get paths that are mount points of /dev/* devices
# select those mount points that are a prefix of $path
# grab the longest prefix path $mpoint
mpoint=$(egrep '^/dev' /etc/mtab |
awk -v "fnm=$path" \
'{ if (index(fnm, $2) == 1) print $2 }' |
sort | tail --lines=1
)
# now print the device that is mounted on $mpoint
egrep '^/dev' /etc/mtab |
awk -v "m=$mpoint" '{ if ($2 == m ) print $1 }'
If you are interested in learning more about
bash,
I can highly recommend this Bash Guide, which assumes that you already know the basics, as explained e.g. in this tutorial.
No comments:
Post a Comment