When working with filesystem-specific features (like extended attributes, ACLs, or compression), we often need to determine the underlying filesystem type and mount point for a given file path. While the mount
command provides this information, parsing its output in scripts can be brittle and platform-dependent.
Here's a more reliable approach that combines several Unix utilities:
#!/bin/bash
filepath="/path/to/your/file"
# Get filesystem device
fs_device=$(df --output=source "$filepath" | tail -n1)
# Get mount point
mount_point=$(df --output=target "$filepath" | tail -n1)
# Get filesystem type
fs_type=$(stat -f -c %T "$filepath")
echo "File: $filepath"
echo "Filesystem device: $fs_device"
echo "Mount point: $mount_point"
echo "Filesystem type: $fs_type"
For more robust handling, consider these scenarios:
# Cross-platform version (works on BSD/macOS too)
if [[ "$(uname)" == "Linux" ]]; then
fs_type=$(stat -f -c %T "$filepath")
else
# BSD/macOS version
fs_type=$(stat -f %T "$filepath")
fi
# Handle symlinks properly
real_path=$(readlink -f "$filepath")
fs_device=$(df --output=source "$real_path" | tail -n1)
On modern Linux systems, findmnt
offers a cleaner interface:
# Get comprehensive filesystem info
findmnt -T "$filepath" -o SOURCE,TARGET,FSTYPE,OPTIONS
# JSON output for parsing
findmnt -J -T "$filepath"
Here's how you might use this in a script handling extended attributes:
check_xattr_support() {
local file=$1
local fs_type=$(stat -f -c %T "$file")
case "$fs_type" in
"ext2"|"ext3"|"ext4"|"xfs"|"btrfs"|"reiserfs"|"jfs")
return 0
;;
*)
echo "Unsupported filesystem: $fs_type" >&2
return 1
;;
esac
}
For scripts processing many files, minimize filesystem calls:
# Cache filesystem info for parent directory
dir_fs=$(stat -f -c %T "/path/to/parent")
file_fs=$(stat -f -c %T "/path/to/parent/file")
if [[ "$dir_fs" != "$file_fs" ]]; then
echo "Warning: File crossed filesystem boundary" >&2
fi
When working with files in Unix-like systems, you might need to determine which filesystem a file resides on, its mount point, and its filesystem type. This is particularly useful for scripts that interact with filesystem-specific features like extended attributes (xattr), disk quotas, or encryption.
The most straightforward method is to parse the output of the mount
command:
mount | grep '/dev'
However, this approach has several drawbacks:
- Output format varies across Unix variants
- Requires complex parsing for reliable results
- Doesn't directly map a file path to its filesystem
A more robust approach combines df
and stat
commands:
# Get the mount point
MOUNTPOINT=$(df --output=target "$FILE" | tail -n 1)
# Get the filesystem type
FSTYPE=$(stat -f -c %T "$FILE")
Different Unix variants may require adjustments:
Linux Systems
# Modern Linux with GNU coreutils
FSTYPE=$(stat -f -c %T "$FILE")
# Alternative using findmnt
MOUNTPOINT=$(findmnt -n -o TARGET --target "$FILE")
macOS (Darwin)
# macOS specific implementation
MOUNTPOINT=$(df "$FILE" | tail -1 | awk '{print $NF}')
FSTYPE=$(diskutil info "$MOUNTPOINT" | grep "Type (Bundle):" | awk '{print $3}')
Here's a portable function that works across most Unix-like systems:
get_filesystem_info() {
local file="$1"
if [ ! -e "$file" ]; then
echo "File does not exist" >&2
return 1
fi
# Get mount point
if command -v findmnt >/dev/null; then
mountpoint=$(findmnt -n -o TARGET --target "$file")
else
mountpoint=$(df --output=target "$file" | tail -n 1)
fi
# Get filesystem type
if [ "$(uname)" = "Darwin" ]; then
fstype=$(diskutil info "$mountpoint" | grep "Type (Bundle):" | awk '{print $3}')
else
fstype=$(stat -f -c %T "$file" 2>/dev/null || df --output=fstype "$file" | tail -n 1)
fi
echo "Mount Point: $mountpoint"
echo "Filesystem Type: $fstype"
}
Consider these special scenarios:
- Bind mounts may show multiple mount points for the same filesystem
- Network filesystems (NFS, SMB) may report differently
- Virtual filesystems (proc, sysfs) have special characteristics
For scripts processing many files:
- Cache filesystem information when possible
- Avoid repeated calls to external commands
- Consider using
/proc/mounts
on Linux for faster access