Clean & eject external drives in macOS
There have been a host of macOS utilities over the years that remove macOS hidden system and metadata files from external drives in order to prevent compatibility issues on devices like MP3 players, car stereos, etc.:
CleanEject: "Remove unwanted hidden files on USB-sticks, cameras, GPSses and other devices"
Eject-for-Windows (GH): "Remove hidden files from removable storages"
CleanAndEject: "Will clean most of the OSX created dot files that pollute every removable drive you plug into your Mac"
CleanMyDrive: "Automatically clean hidden junk from external drives" (now bundled into CleanMyMac)
Hidden Cleaner: Removes macOS 'ghost' files from devices like MP3 players and USB drives before ejecting them, preventing playback errors and compatibility issues
HiM (Hidden Cleaner iMproved): "Cleans and ejects USB devices like MP3 players, USB sticks... (and also local folders)"
USBclean: "Quickly and easily remove pesky junk and ghost files from your external USB drives"
BlueHarvest: "Removes .DS_Store and ._ AppleDouble files from your USB keys, SD cards, music players, file servers or any non Mac disk"
Hidden File Cleaner: "Ensures annoying hidden files don't clutter your drives"
Bash
The developer of CleanEject kindly posted a Bash script that does the job admirably (tested in macOS Sequoia):
#!/bin/bash
if [ -d "$1/.Spotlight-V100" ]; then
dot_clean -m "$1"
find "$1" -name .DS_Store -o -name .apdisk -delete
rm -rf "$1/.Trashes"
rm -rf "$1/.Spotlight-V100"
rm -rf "$1/.fseventsd"
rm -rf "$1/.TemporaryItems"
hdiutil unmount "$1"
fi
Here's a slightly modified version that does not require .Spotlight-V100
to be present, fixes .DS_Store
deletion, and uses a safer eject method:
#!/bin/bash
if [ -d "$1" ]; then
dot_clean -m "$1"
find "$1" \( -name .DS_Store -o -name .apdisk \) -type f -delete
rm -rf "$1"/{.Trashes,.Spotlight-V100,.fseventsd,.TemporaryItems}
diskutil eject "$1"
fi
AppleScript
The modified version wrapped in AppleScript for a simple GUI volume chooser (assuming the user can be trusted not to select Macintosh HD, Time Machine volumes, etc.):
set selectedVolume to choose folder with prompt "Select drive to clean and eject:" default location (POSIX file "/Volumes")
set volumePath to POSIX path of selectedVolume
do shell script "
if [ -d '" & volumePath & "' ]; then
dot_clean -m '" & volumePath & "'
find '" & volumePath & "' \\( -name .DS_Store -o -name .apdisk \\) -type f -delete
rm -rf '" & volumePath & "'/{.Trashes,.Spotlight-V100,.fseventsd,.TemporaryItems}
diskutil eject '" & volumePath & "'
fi"
To reduce the risk of mishap, this final attempt ("One more coruscation, my dear Watson—yet another brain-wave!") processes only FAT and exFAT-formatted volumes:
set selectedVolume to choose folder with prompt "Select drive to clean and eject:" default location (POSIX file "/Volumes")
set volumePath to POSIX path of selectedVolume
-- Only allow FAT family and exFAT
set fsType to do shell script "diskutil info -plist " & quoted form of volumePath & " | plutil -extract FilesystemType raw -"
if fsType is not in {"msdos", "exfat", "fat16", "fat32"} then
display alert "Unsupported Volume" message "Only FAT16, FAT32 and exFAT volumes are supported for safety" buttons {"OK"} default button "OK"
return
end if
-- Clean the volume
do shell script "
dot_clean -m " & quoted form of volumePath & " 2>/dev/null || true
find " & quoted form of volumePath & " \\( -name .DS_Store -o -name .apdisk \\) -type f -delete 2>/dev/null || true
rm -rf " & quoted form of volumePath & "/.Trashes " & quoted form of volumePath & "/.Spotlight-V100 " & quoted form of volumePath & "/.fseventsd " & quoted form of volumePath & "/.TemporaryItems 2>/dev/null || true
"
-- Eject
try
do shell script "diskutil eject " & quoted form of volumePath
on error
display alert "Eject Failed" message "Cleaning completed but eject failed" buttons {"OK"} default button "OK"
end try
Save either AppleScript script in Script Editor via File → Export... → File Format: Application → Code sign: Sign to Run Locally, then grant Accessibility and Full Disk Access permissions in System Settings/Privacy & Security.
Using File → Save... → File Format: Application instead or not granting the necessary permissions will prevent the app from removing
.Trashes
and.Spotlight-V100
.Script Editor sometimes failed to generate
Contents/_CodeSignature/CodeResources
inside the exported app, preventing proper handling of.Trashes
and.Spotlight-V100
. Toggling Code Sign: to Don't Code Sign then back to Sign to Run Locally before saving resolved the issue.TCC permissions occasionally failed despite valid entitlements and pre-approved access, blocking deletion of
.Trashes
and.Spotlight-V100
; renaming the exported app and re-granting permissions resolved the issue.
Related
Why are my Applescript scripts executing in ScriptEditor but not as an application?
How can I get my script exported as an app to stop asking for permissions
❧ 2025-09-01