Skip to main content

Umount & Clean your NTFS/exFAT partition from macOS using Python

Jose CerrejonAbout 2 minApple

Umount & Clean your NTFS/exFAT partition from macOS using Python

external hard drive
My external hard drive with tons of 💩.

Sometimes I think I'm the one who has problems with the NTFS/exFAT partition on macOS. I have to unmount and clean it, because exFAT is the file system I use on a Raspberry Pi acting as NAS using the great DietPi OSopen in new window.


exFAT because is one of the file system that is compatible with macOS, Windows and Linux. Eject the hard drive is not enough, so I had to make a python script code that help me on that. So here it is:

import subprocess
import os

def main():
    volumes = subprocess.run(['mount'], stdout=subprocess.PIPE).stdout.decode('utf-8').split('\n')

    for volume in volumes:
        if 'on /Volumes/' in volume and 'nodev' in volume:
            volume_name = volume.split()[2]
            clean_volume(f"{volume_name}/pelis" if os.path.isdir(f"{volume_name}/movies") else f"{volume_name}")

            subprocess.run(["diskutil", "unmountDisk", f"{volume_name}"])

def clean_volume(volume_name):
    print(f"\nFound: {volume_name}. Cleaning...")
    subprocess.run(["rm", "-rf", f"{volume_name}/.Trashes {volume_name}/.fseventsd {volume_name}/.Spotlight-V100"])
    subprocess.run(["find", volume_name, "-type", "f", "-name", "._*", "-depth", "-delete"])
    subprocess.run(["find", volume_name, "-type", "f", "-name", ".DS*", "-depth", "-delete"])


if __name__ == "__main__":
    main()

The code is pretty simple. It uses the subprocess module to run terminal commands and the os module to check if a directory exists. The main function runs the following commands:

  • subprocess.run(['mount'], stdout=subprocess.PIPE).stdout.decode('utf-8').split('\n'): This command runs the mount command in the terminal, which save in a variable all volumes mounted on the system. The output is decoded into a string and split into lines, and looped through each one.

  • if 'on /Volumes/' in volume and 'nodev' in volume: This conditional checks if the current line from the mount command is a volume under /Volumes and if it's a nodev volume, which is a type of volume that is not associated with any device.

  • clean_volume(f"{volume_name}/pelis" if os.path.isdir(f"{volume_name}/pelis") else f"{volume_name}"): This line calls the clean_volume function on the volume. If the volume has a directory named movies, that directory is cleaned. If not, the entire volume is cleaned.

  • subprocess.run(["diskutil", "unmountDisk", f"{volume_name}"]): This command unmounts the volume from the system.

The clean_volume function runs several commands to clean the volume:

  • subprocess.run(["rm", "-rf", f"{volume_name}/.Trashes {volume_name}/.fseventsd {volume_name}/.Spotlight-V100"]): This command removes several directories that macOS uses to store system and cache files.

  • subprocess.run(["find", volume_name, "-type", "f", "-name", "._*", "-depth", "-delete"]): This command finds and deletes all files beginning with ._, which are files created by macOS to store file metadata on filesystems that do not support file metadata in the same way as macOS.

  • subprocess.run(["find", volume_name, "-type", "f", "-name", ".DS*", "-depth", "-delete"]): This command finds and deletes all files beginning with .DS, (same as ._).

I hope it helps you!