macOS Trash and .DS_Store: Deleted File Evidence
The macOS Trash keeps deleted files with their original location in .DS_Store put-back records, showing what a user deleted, from where and when.
- Location
- ~/.Trash/ and /Volumes/<volume>/.Trashes/<uid>/
- Proves
- Which files a user moved to the Trash, their original folder and name, and roughly when they were trashed
- Timestamps
- File system times of the trashed item (ctime changes on the move); .DS_Store modD/moDD in Mac absolute time
- Access
- Owning user; ~/.Trash is TCC-protected for other apps, so the collector needs Full Disk Access
- Retention
- Until the Trash is emptied, or 30 days if Remove items from the Trash after 30 days is enabled
- Collection
- UAC, Aftermath, mac_apt, ditto
Tools
Compare all tools- mac_aptCLI · open source
- DSStoreParserCLI · open source
- statCLI · built into macOS
What it is
When a user deletes a file in Finder (Move to Trash, Command-Delete or drag to the Dock), macOS does not delete it: it renames and moves it into a per-user Trash folder. Finder then records where the item came from in the .DS_Store file of that Trash folder, so that Put Back can restore it. Those put-back records are the macOS equivalent of the $I files in the Windows Recycle Bin.
Command-line deletion (rm, unlink, scripts, most malware clean-up) bypasses the Trash entirely. An empty Trash on a system where the user clearly worked with files is itself a data point.
Where it lives
| Source | Path | Notes |
|---|---|---|
| Boot volume Trash | ~/.Trash/ | One per user, mode 700 |
| Put-back records | ~/.Trash/.DS_Store | Written by Finder only |
| Other volumes | /Volumes/<name>/.Trashes/<uid>/ | Per-UID folder on each external or secondary volume |
| Settings | ~/Library/Preferences/com.apple.finder.plist | Finder settings; the 30-day auto-empty option is commonly reported as FXRemoveOldTrashItems |
On a dead-box image, user homes are under /System/Volumes/Data/Users/. On external media, .Trashes holds one folder per numeric UID, which ties deleted items on a USB stick back to an account on the Mac that deleted them (see USB devices).
What it proves
- That a specific file sat in the Trash at acquisition time, with its content intact.
- Its original folder (
ptbL) and original name (ptbN) when Finder renamed it to avoid a name clash in the Trash. - Which account deleted it, from the Trash folder owner or the UID folder in
.Trashes. - That a Trash was emptied, indirectly: FSEvents records the removal of paths under
.Trash, and a.DS_Storethat still lists entries whose files are gone suggests a partial or scripted clean-up.
It does not prove who pressed delete when several people share an account, and it says nothing about files removed with rm.
Key fields
.DS_Store is a Finder "Buddy Allocator" B-tree of records keyed by file name plus a four-character code. For the Trash, the useful codes are:
| Code | Type | Meaning |
|---|---|---|
ptbL | string | Put-back location: original parent folder, relative to the volume root |
ptbN | string | Put-back name: original file name when it differs from the name in the Trash |
modD / moDD | double | Modification date as seen by Finder, Mac absolute time |
lg1S / ph1S | integer | Logical and physical size |
Items dropped into the Trash by other applications through the NSFileManager trash API may lack put-back records. Treat a missing ptbL as "unknown origin", not as evidence of tampering.
Timestamps
Moving a file within the same volume is a rename, so the trashed item keeps its birth and modification times and its change time (ctime) updates to the moment it was trashed. The parent .Trash folder's modification time moves every time an item enters or leaves. Read all four with:
stat -f '%SB | %Sm | %Sc | %N' -t '%Y-%m-%dT%H:%M:%S%z' ~/.Trash/*
Moving across volumes is a copy then delete, which gives the item a new birth time. modD values in .DS_Store are Mac absolute time (seconds since 2001-01-01 UTC).
Retention
- Items stay until the user empties the Trash, deletes an item from it, or the 30-day option removes it.
- Emptying the Trash unlinks the files. On APFS with TRIM on SSDs, recovery of the content from free space is usually not realistic; older versions may survive in APFS snapshots and Time Machine.
.DS_Storekeeps records for a while after items leave; do not assume every record matches a present file.
Collection
sudo ditto ~/.Trash ./case/Trash_<user>
sudo ditto /Volumes/<name>/.Trashes ./case/Trashes_<name>
- UAC collects
~/.Trashand/Volumes/*/.Trashes. - Aftermath lists the contents of each user's
.Trash(paths only). - mac_apt
TRASHparses~/.Trash/.DS_Storeand joins it with the items present.
The Terminal needs Full Disk Access to list ~/.Trash on current releases; without it ls returns "Operation not permitted".
Parsing
# Put-back records with mac_apt
python3 mac_apt.py -o out E01 image.E01 TRASH
# Stand-alone .DS_Store parsing
python3 DSStoreParser.py -s ./case/Trash_<user> -o ./out
DSStoreParser walks every .DS_Store in a tree, which is also useful outside the Trash: Finder view records list file names that existed in a folder when it was last viewed.
Investigator tips
- Build the story from three angles:
ptbL(where it came from), ctime (when it was trashed) and FSEvents (renames into.Trash, then removals when emptied). - Check
.Trasheson every attached or imaged external volume. A USB stick that was "cleaned" on the Mac often still holds a.Trashes/501folder. - Spotlight may still index a trashed file; see Spotlight store.
- Recently used lists in Recent Items and app MRUs can point at files that now only exist in the Trash, or nowhere.
- Deleted items in Photos, Notes, Mail and Messages use their own "Recently Deleted" areas, not
~/.Trash.