Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I check if /my/dir is on the same partition as /?

This is for integration within a script. Bind mounts should be handled correctly. POSIX compatible solutions are welcome.

share|improve this question
    
“Bind mounts should be handled correctly.” But what do you consider correct? Your question can be interpreted either way. –  Gilles Apr 30 at 15:34
    
@Gilles In the original title I wrote "hosted" instead of "mounted", someone edited adding confusion IMHO. Yet my question body is clear: "on the same partition", that is on the same physical partition, whatever the path or mountpoint used to access the two files / directories. –  Totor Apr 30 at 15:51

3 Answers 3

test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1

Works with any number of paths.

share|improve this answer
    
Parsing the output of df is not always a good idea. –  Joseph R. Mar 21 at 16:36
    
@JosephR Good point, thanks. –  n.st Mar 21 at 16:37
1  
@Totor I'm checking the mountpoint ($6), not the device name ($1), so that shouldn't be a problem. –  n.st Mar 21 at 16:41
1  
@JosephR It's the best there is in POSIX. n.st: why not check the first field? It doesn't matter which path was used to access the device, if it's the same mount point then the output will be consistent. –  Gilles Mar 21 at 17:32
    
This does not work with bind mounts. –  Totor Apr 30 at 13:36

You can check this with stat:

$ stat -c '%d %m' /proc/sys/
3 /proc

Shows you the device number and where your directory was mounted.

share|improve this answer
1  
Nice, but the stat shell command is not POSIX... –  Totor Mar 21 at 16:58
    
No? How do you know? –  bersch Mar 21 at 17:11
    
Not in this list. –  Totor Mar 21 at 17:13
    
Oh, my bad. But next time show this link in advance. –  bersch Mar 21 at 17:15

The following command gives a unique name for the mount point containing the file $file:

df -P -- "$file" | awk 'NR==2 {print $1}'

This works on any POSIX system. The -P option imposes a predictable format; the first field of the second line is the “file system name”. Thus, to check two files are under the same mount point:

if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
     "$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

Or, to save a couple of process invocations:

if df -P -- "$file1" "$file2" |
   awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
  echo "$file1 and $file2 are on the same filesystem" ; fi

A few operating systems can have spaces in volume names. There's no completely reliable way of parsing the df output in this case.

Under the hood, you can identify the filesystem containing a file by the st_dev field returned by stat. There's no portable way to do this from a shell script. Some systems have a stat utility, but its syntax varies:

  • On non-embedded Linux, Cygwin or other systems with GNU coreutils, stat reports the st_dev field when invoked as stat -c %D -- "$file".
  • Some BusyBox installations include a stat which is compatible with GNU coreutils. Others have stat without the %c option; you can use stat -t -- "$file" | awk '{print $8}' but this only works if the file name does not contain whitespace, or stat -t -- "$file" | awk 'END {print $(NF-8)}' which copes with arbitrary file names but not with future additions of fields to the stat output.
  • BSD systems have a different stat utility which requires stat -f %d -- "$file".
  • Solaris, AIX and others have no stat utility.

If Perl is available, you can use

perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"

and to do the comparison:

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"

Note that there are some corner cases where the desired result is not clear. For example, with Linux's bind mounts, after mount --bind /foo /bar, /foo and /bar are considered to be the same filesystem. It is always possible that the two files are actually located on the same device but you'll never know: for example, if the files are on two different network mounts, the client has no way to know whether the server is exporting different filesystems.

If the files are directories and you can write to them, another method is to create a temporary file and attempt to make a hard link. This one reports a negative result across Linux bind mounts.

tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
  echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"
share|improve this answer
    
Problem: df does not always give the device name, but sometime a symlink to it like /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4 making df not reliable. The only reliable option so far is using a stat-based solution. –  Totor Apr 30 at 14:19
    
@Totor That doesn't matter: whatever name df reports for the device, it is consistent between the two invocations, so it's ok for a comparison. –  Gilles Apr 30 at 14:50
    
No, it doesn't work, I tested it. On Debian Wheezy here, a single df reports /dev/sda6 and /dev/disk/by-uuid/ca09b..., both referring to the same device, but different mount points. The string comparison test obviously fails when trying with files from each mount point. –  Totor Apr 30 at 15:20
    
@Totor Normally you can't have the same block device mounted twice. As I indicate in my answer, there are corner cases such as bind mounts which may or may not be reported as distinct. –  Gilles Apr 30 at 15:33
    
Yet it works perfectly on Debian Squeeze and Wheezy: mount /dev/sda6 /mnt1 followed by mount /dev/sda6 /mnt2 works like a charm. cat /proc/mounts is fine with it. However, it is only since Wheezy that /dev/disk/by-uuid/ca09b... is shown in df as the device for the root filesystem. Further attempts to mount it using this simlink or the UUID=ca09b... mount syntax do not end showing anything else than /dev/sda6 in df (I don't know how to reproduce what it done during the boot process, but that is not the concern here). –  Totor Apr 30 at 16:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.