It is useful to be able to mount your Raspberry Pi's file system on your Mac's desktop. The Raspberry Pi is ready to rock-'n-roll but some work needs to be done on the Mac. This gist assumes macOS Mojave 10.14. Your mileage may vary on earlier or later versions.
You can make your life quite a bit simpler if you set up SSH on your Mac so that it can login to your Raspberry Pi without needing a password. Follow this tutorial.
The tutorial assumes two Raspberry Pis but there is no difference in approach if you use a Mac and a Pi, or two Macs.
If you don't have HomeBrew installed on your Mac, follow the installation instructions.
To install the Secure-Shell File System support (SSHFS):
-
If you have worked through these instructions before but are now getting errors from Homebrew like this:
Error: sshfs has been disabled because it requires closed-source macFUSE!
the first thing you need to do is to un-install the old version of sshfs:
$ brew update $ brew uninstall sshfs
-
Either:
- Go to osxfuse.github.io
- Download the latest installer
- Run the installer
or, if MacFUSE is already installed:
- Open "System Preferences"
- Click "MacFUSE"
- Click "Check for updates" and follow your nose.
-
Install SSHFS:
$ brew install gromgit/fuse/sshfs-mac
See also gromgit/homebrew-fuse.
To install the Secure-Shell File System support (SSHFS), do:
$ brew update
$ brew install sshfs
A mount-point is just a folder. It can be anywhere on your Mac. Your home directory is just as good as anywhere else.
For example, if you have given your Raspberry Pi the name "mypi" then you could create the mount-point folder like this:
$ mkdir ~/mypi
This folder is only "special" when it is being used as a mount point. Otherwise, it is just an ordinary folder.
The syntax is:
sshfs «user»@«host»: «mountPoint»
where:
-
«user» is the username on the Raspberry Pi (eg "pi"). This field and the trailing
@
can be omitted if you set up an ssh config. -
«host» is an identifier for the Raspberry Pi. It could be:
-
an IP address - eg "192.168.203.10"
-
a multicast DNS name - eg "mypi.local"
-
a fully-qualified domain name - eg "mypi.mydomain.com"
-
the ssh host identifier - eg "mypi" - providing you have set up an ssh config. A typical entry would be:
host mypi # enable whichever form of "hostname" is most appropriate hostname 192.168.203.10 # hostname mypi.local # hostname mypi.mydomain.com user pi UseKeychain yes
-
-
«mountPoint» is the path to the mount point created in the previous step
Note the trailing colon and space separating the «host» from the «mountPoint». Don't omit either of those characters!
Examples:
$ sshfs [email protected]: ~/mypi
$ sshfs [email protected]: ~/mypi
$ sshfs [email protected]: ~/mypi
$ sshfs mypi: ~/mypi
Always be very careful to get the "«user»@«host»" exactly right. Any mistake can hang this command, hang the Finder (spinning beachball) and result in the need for a forced power-off/power-on. If you happen to have another Terminal window open, you can get away with a "killall sshfs" but that still leaves the mount point in an indeterminate state and a restart is the only way to recover. Not very Mac-like, I know.
The first time you run sshfs
, your action will almost certainly be blocked by that ever-present pestilence masquerading as a benevolent computer nanny: GateKeeper. You will need to navigate to the "Security & Privacy" panel of "System Preferences", authenticate, and permit the action.
The remote volume will mount on your desktop. You can copy files into and out of the Raspberry Pi's volume. You can also access the remote volume from the macOS Terminal like this:
$ cd ~/mypi
When you are finished, drag the volume to the trash to eject it. Alternatively, you can un-mount it from macOS Terminal like this:
$ umount ~/mypi
You can save yourself some time and avoid having to remember the sshfs
command syntax by creating a "mount script" for each of your Raspberry Pis:
-
Copy the content below into a text editor:
#!/usr/bin/env sh RASPBERRYPI="mypi" MOUNTPOINT="$HOME/$RASPBERRYPI" # ensure mount point exists (non-destructive) mkdir -p "$MOUNTPOINT" # mount the volume sshfs "$RASPBERRYPI": "$MOUNTPOINT" -ovolname="$RASPBERRYPI" # reminder echo "Unmount $RASPBERRYPI by dragging to trash or type 'umount $MOUNTPOINT'"
-
Edit the "RASPBERRYPI" variable so that it equals the name of your Raspberry Pi.
-
Save the file in your search path (eg
~/.local/bin
) with a name like "mount_mypi".
Once you have done that, you can mount your Raspberry Pi's home folder by typing:
$ mount_mypi
Notes:
-
Don't worry about the
mkdir -p
command. It is completely non-destructive:- If the folder already exists,
mkdir -p
does absolutely nothing. - If the folder already exists and contains files and folders when this script is run, those become inaccessible while the folder is being used as a mount-point. As soon as you dismount the remote volume, the folder goes back to being a regular folder with its contents are intact.
- If the folder already exists,
-
The script structure assumes that the "RASPBERRYPI" variable equals a host identifier defined in your ssh config. You will need to adjust the
sshfs
command if you have not set up an ssh config.
Resource Forks hail from the original "classic" Mac of the 1980s and were inherited by Mac OS X (since renamed macOS). The easiest way to understand what a Resource Fork represents is to visualise how any computer file system must work. At its simplest, a directory is just a table where each row contains a file name and a pointer to the start of the file's data on the disk:
FileName | Data |
---|---|
fred.txt | 5 |
freddy.txt | 7 |
In words: the data for the file
fred.txt
starts at sector 5; and the data for the filefreddy.txt
starts at sector 7.
In a macOS file system, each row in the directory has two pointers, one to the Data Fork and the other to the Resource Fork:
FileName | Data | Resource |
---|---|---|
fred.txt | 5 | |
freddy.txt | 7 | 15 |
In words: the Data Fork for the file
fred.txt
starts at sector 5 but it does not have a Resource Fork; the Data Fork for the filefreddy.txt
starts at sector 7, and its Resource Fork starts at sector 15.
The Data Fork meets the standard definition of a computer file on any operating system: an unstructured sequence of bytes where any structure is imposed by the application(s) that read or write the file. The structure of the Resource Fork has always been defined by macOS and can be thought of as a kind of key-value store.
The purpose of the Resource Fork changed when Mac OS X came along and is now mostly used to store extended attributes. Not every file has extended attributes so, most of the time, there will be no Resource Fork. But, when a non-Mac file system (eg your RPi ext4 partition) is mounted on a Mac and something happens on the Mac side which causes the file to acquire a resource fork, a hidden shadow file will turn up to hold the data associated with the resource fork.
The shadow files all begin with ._
(dot underscore). For example (from macOS Terminal):
$ ls -lno .DS_Store freddy.txt ._*
-rw-r--r--@ 1 501 8196 Aug 15 18:32 .DS_Store
-rw-r--r-- 1 501 4096 Aug 15 14:18 ._.DS_Store
-rw-r--r-- 1 501 4096 Aug 16 10:08 ._freddy.txt
-rw-r--r--@ 1 501 9 Aug 16 10:08 freddy.txt
.DS_Store
and freddy.txt
are Data Forks while ._.DS_Store
and ._freddy.txt
are Resource Forks. The "@" at the end of the file flags for the two Data Forks means "extended attributes are defined" so that's also a clue to the presence of a Resource Fork. We can ask macOS to tell us what those extended attributes are (from macOS Terminal):
$ ls -@lno .DS_Store freddy.txt
-rw-r--r--@ 1 501 8196 Aug 15 18:32 .DS_Store
com.apple.FinderInfo 32
-rw-r--r--@ 1 501 9 Aug 16 10:08 freddy.txt
com.apple.metadata:_kMDItemUserTags 42
If you run the same commands from the Raspberry Pi OS command line:
$ ls -lno .DS_Store freddy.txt ._*
-rw-r--r-- 1 1000 4096 Aug 15 14:18 ._.DS_Store
-rw-r--r-- 1 1000 8196 Aug 15 18:32 .DS_Store
-rw-r--r-- 1 1000 4096 Aug 16 10:08 ._freddy.txt
-rw-r--r-- 1 1000 9 Aug 16 10:08 freddy.txt
$ ls -@lno .DS_Store freddy.txt
ls: invalid option -- '@'
Try 'ls --help' for more information.
In short, Raspberry Pi OS can see the hidden shadow files but has no idea what they mean.
Most of the time the hidden shadow files don't cause any problems but you may find them showing up in unexpected places such as git status
if you have not told git
to ignore them.
It causes no harm whatsoever to simply remove the hidden shadow files. I define this alias in my Raspberry Pi OS profile for the purpose:
alias KILLRESOURCEFORKS='sudo find . -name "._*" -delete'
Whenever I spot an unwanted resource fork, I type "K" and hit tab
which auto-completes to KILLRESOURCEFORKS, and then I hit ⏎. All gone!
and, while we're on the topic of hidden macOS files…
A similar comment applies to .DS_Store files. These are (roughly) equivalent to Thumbs.db
on Windows. I define another alias to get rid of those when I see them:
alias DSSTORES='sudo find . -type f \( -name ".DS_Store" -o -name "._.DS_Store" \) -delete'
Rest assured, removing these files is harmless to both Raspberry Pi OS and macOS.