How to recover deleted files from a hard drive using python (illustration with MacOs) ?

Published: October 03, 2023

Tags: Python;

DMCA.com Protection Status

I inadvertently deleted numerous pictures (in png and jpeg formats) that were stored within a folder on my external hard drive, and subsequently emptied my trash.

In this note, I will demonstrate the process of file recovery. Although I am using a Mac, the underlying logic is similar for Windows systems.

Even if you've emptied your computer's trash, the information is still present. Retrieving it is possible as long as you don't add new files to your disk. In that case, overwriting the deleted file's information becomes feasible. When you empty the trash, you essentially tell your computer that it can utilize that space to store new data.

Felipe's post provided invaluable assistance (can be found here). Here, I'll share the steps I followed on my MAC for your reference.

Find disk name on MAC

To access your external disk as raw bytes, you must first obtain the disk name.

Connected to my MAC studio are two external hard drives named HD2 and HD15TB. The deleted files were stored on the HD2 drive. To retrieve disk name, please launch a terminal and enter the following command:

diskutil list

gives for example

#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                         1.0 TB     disk0
1:             Apple_APFS_ISC ⁨⁩                        524.3 MB   disk0s1
2:                 Apple_APFS ⁨Container disk3⁩         994.7 GB   disk0s2
3:        Apple_APFS_Recovery ⁨⁩                        5.4 GB     disk0s3

/dev/disk3 (synthesized):
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      APFS Container Scheme -                      +994.7 GB   disk3
                              Physical Store disk0s2
1:                APFS Volume ⁨Macintosh HD⁩            23.4 GB    disk3s1
2:              APFS Snapshot ⁨com.apple.os.update-...⁩ 23.4 GB    disk3s1s1
3:                APFS Volume ⁨Preboot⁩                 490.4 MB   disk3s2
4:                APFS Volume ⁨Recovery⁩                1.6 GB     disk3s3
5:                APFS Volume ⁨Data⁩                    879.1 GB   disk3s5
6:                APFS Volume ⁨VM⁩                      18.3 GB    disk3s6

/dev/disk4 (external, physical):
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *5.0 TB     disk4
1:                        EFI ⁨EFI⁩                     209.7 MB   disk4s1
2:                  Apple_HFS ⁨HD2⁩                     5.0 TB     disk4s2
                 (free space)                         134.4 MB   -

/dev/disk5 (external, physical):
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *14.0 TB    disk5
1:                        EFI ⁨EFI⁩                     209.7 MB   disk5s1
2:                  Apple_HFS ⁨HD15TB⁩                  14.0 TB    disk5s2
                 (free space)                         135.2 MB   -

One can see that HD2 is associated with disk4 IDENTIFIER.

Use python to recover deleted files

Example recover JPEG images

Create a folder to store all the images you will retrieved, and a Python script:

touch recover_deleted_files.py

edit the file to recover :

#import sys $ TESTING

drive = "/dev/disk4"     # Open drive as raw bytes
fileD = open(drive, "rb")
size = 512              # Size of bytes to read
byte = fileD.read(size) # Read 'size' bytes
offs = 0                # Offset location
drec = False            # Recovery mode
rcvd = 0                # Recovered file ID
while byte:
    found = byte.find(b'\xff\xd8\xff\xe0\x00\x10\x4a\x46')
    if found >= 0:
        drec = True
        print('==== Found JPG at location: ' + str(hex(found+(size*offs))) + ' ====')
        fileN = open(str(rcvd) + '.jpg', "wb")
        fileN.write(byte[found:])
        while drec:
            byte = fileD.read(size)
            bfind = byte.find(b'\xff\xd9')
            if bfind >= 0:
                fileN.write(byte[:bfind+2])
                fileD.seek((offs+1)*size)
                print('==== Wrote JPG to location: ' + str(rcvd) + '.jpg ====\n')
                drec = False
                rcvd += 1
                fileN.close()
            else: fileN.write(byte)
        # Now lets create recovered file and search for ending signature
        #sys.exit() # TESTING
    byte = fileD.read(size)
    offs += 1
fileD.close()

Now to execute the script if you do

python recover_deleted_files.py

you will get the following error

PermissionError: [Errno 13] Permission denied: '/dev/disk4'

because you need admin privileges to access disk4.

So, open a terminal and launch python with admin privileges:

sudo python recover_deleted_files.py

Example recover PNG images

I made a slight modification to the code to retrieve a PNG image. To achieve this, the code first searches for the hexadecimal signature that indicates the start of a PNG file (b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a'). Additionally, I replaced the IEND for the PNG with 4 bytes (b'\xae\x42\x60\x82').

#import sys # TESTING

drive = "/dev/disk4"     # Open drive as raw bytes
fileD = open(drive, "rb")
size = 512              # Size of bytes to read
byte = fileD.read(size) # Read 'size' bytes
offs = 0                # Offset location
drec = False            # Recovery mode
rcvd = 0                # Recovered file ID
while byte:
    found = byte.find(b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a')
    if found >= 0:
        drec = True
        print('==== Found PNG at location: ' + str(hex(found+(size*offs))) + ' ====')
        fileN = open(str(rcvd) + '.png', "wb")
        fileN.write(byte[found:])
        while drec:
            byte = fileD.read(size)
            bfind = byte.find(b'\xae\x42\x60\x82')
            if bfind >= 0:
                fileN.write(byte[:bfind+4])
                fileD.seek((offs+1)*size)
                print('==== Wrote PNG to location: ' + str(rcvd) + '.png ====\n')
                drec = False
                rcvd += 1
                fileN.close()
            else: fileN.write(byte)
        # Now lets create recovered file and search for ending signature
        #sys.exit() # TESTING STOP AFTER FINDING FIRST PNG IMAGE
    byte = fileD.read(size)
    offs += 1
fileD.close()

Hope it helps.

Please keep in mind that if you accidentally delete some files, it is still theoretically possible to recover them, even if you have emptied your trash !

It's important to also keep in mind that hackers have the ability to access personal information, even if you believe you have thoroughly deleted everything from your computer.

Other solution(s)

If you encounter any difficulties while implementing the Python solution, there are alternative approaches available. For instance, you can explore downloading applications to your computer that offer file recovery services. However, keep in mind that while some may offer free trials, there may be a cost associated with their full functionality.

Disk Drill

For instance, I experimented with an application called Disk Drill (disk-drill) for both Windows and Mac, and it performed well.

References