title: Give the mount point of a path
body: <p>The following, very non-robust shell code will give the mount point of <code>$path</code>:</p>
  
  <pre>
   (for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;; esac; done) | tail -n 1
  </pre>
  
  <p>Is there a better way to do this in shell?</p>
  
  <p><strong>Postscript</strong></p>
  
  <p>This script is really awful, but has the redeeming quality that it Works On My Systems.  Note that several mount points may be prefixes of <code>$path</code>. </p>
  
  <p><strong>Examples</strong>
  On a Linux system:</p>
  
  <pre>
  cas@txtproof:~$ path=/sys/block/hda1
  cas@txtproof:~$ for i in $(df -a|cut -c 57-99); do case $path in $i*) echo $i;; esac; done| tail -1
  /sys
  </pre>
  
  <p>On a Mac OSX system</p>
  
  <pre>
  cas local$ path=/dev/fd/0
  cas local$ for i in $(df -a|cut -c 63-99); do case $path in $i*) echo $i;; esac; done| tail -1
  /dev
  </pre>
  
  <p>Note the need to vary cut's parameters, because of the way df's output differs; using awk solves this, but even awk is non-portable, given the range of result formatting various implementations of df return.</p>
  
  <p><strong>Answer</strong>
  It looks like munging tabular output is the only way within the shell, but </p>
  
  <pre>
  df -P "$path"  | tail -1 | awk '{ print $NF}'
  </pre>
  
  <p>based on ghostdog74's answer, is a big improvement on what I had.  Note two new issues: firstly, <code>df $path</code> insists that <code>$path</code> names an existing file, the script I had above doesn't care; secondly, there are no worries about dereferencing symlinks.  This doesn't work if you have mount points with spaces in them, which occurs if one has removable media with spaces in their volume names.</p>
  
  <p>It's not difficult to write Python code to do the job properly.</p>