Friday, October 6, 2023

Fixing Created Date 1970 For Blu-ray In macOS

Blu-ray is a good way to store data for archival purposes. macOS has built-in support for writing blu-ray disks. However there is an issue with file creation date. All files Created date gets reset to 1 January 1970 at 5:30 AM. This the unix epoch time. Clearly this makes lot of things difficult. This issue is present for years and still not fixed with macOS Ventura. I checked the date at a later point in time and by then I have most of my image files written into blu-ray. This makes ordering files by created date difficult and also it's a bug. Luckily we have two other attributes to our rescue. Photos taken by iPhone have Content Created attribute. This value is intact and so is Modified. If you don't edit you image files, then any of these are valid. So I created a little bash script to update the Created date to Content Created date if it is valid or use Modified.
#!/bin/bash

resetted_date="1970-01-01 00:00:00 +0000"
resetted_content_created_date="1970-01-01 00:00:00 +0000"

function update_created_date {
  local file="$1"

  fs_created_date_utc=$(mdls "$file" | grep "kMDItemFSCreationDate" | awk -F '= ' '{print $2}')
  fs_created_date_local=$(date -j -f "%Y-%m-%d %H:%M:%S %z" "$fs_created_date_utc" "+%m/%d/%Y %H:%M:%S %z")

  
  # Get the kMDItemContentCreationDate value
  content_created_date_utc=$(mdls "$file" | grep "kMDItemContentCreationDate[^_]" | awk -F '= ' '{print $2}')
  content_created_date_local=$(date -j -f "%Y-%m-%d %H:%M:%S %z" "$content_created_date_utc" "+%m/%d/%Y %H:%M:%S %z")

  
  fs_modified_date_utc=$(mdls "$file" | grep "kMDItemFSContentChangeDate" | awk -F '= ' '{print $2}')
  fs_modified_date_local=$(date -j -f "%Y-%m-%d %H:%M:%S %z" "$fs_modified_date_utc" "+%m/%d/%Y %H:%M:%S %z")

  # Check if creation date is not empty and fs created date got reset to 1970
  if [ "$fs_created_date_utc" == "$resetted_date" ] && [ -n "$content_created_date_utc" ] && [ "$content_created_date_utc" != "$resetted_content_created_date" ]; then
    SetFile -d "$content_created_date_local" "$file"
    echo "Content created date set $content_created_date_local for $file"
  elif [ "$fs_created_date_utc" == "$resetted_date" ]; then
    SetFile -d "$fs_modified_date_local" "$file"
    echo "Modified date set $fs_modified_date_local for $file"
  fi
}

# Check for folder path arg
if [ $# -ne 1 ]; then
  echo "Usage: $0 "
  exit 1
fi

folder_path="$1"

# Check if the folder exists
if [ ! -d "$folder_path" ]; then
  echo "Folder '$folder_path' not found."
  exit 1
fi

# recursively process files in folder
while IFS= read -r -d '' file; do
  if [ -f "$file" ] || [ -d "$file" ]; then
    if [ "$(basename "$file")" != ".DS_Store" ]; then  # ignore .DS_Store
      update_created_date "$file"
    fi
  fi
done < <(find "$folder_path" -type f -print0)

# recursively update created for the directory as well
while IFS= read -r -d '' dir; do
  if [ -d "$dir" ]; then
    update_created_date "$dir"
  fi
done < <(find "$folder_path" -type d -print0)

Run this script by specifying the folder like set-created-date-to-image-date Pictures-2018. It will recusively set the created date for folders and files.

The above script will fix the date problem. To prevent this issue with blu-ray disk image writing, one solution is to create a dmg container and format it into the same file system type used by the macOS. I use APFS case-sensitive. So I use the same format as the dmg as well.

To create a new disk image, open Disk Utility > File > New Image > Blank Image and set the parameters as below.
Name: beetles-all-the-way
Size: 25GB
Partitions: Single parition - GUID Partition Map
Format: APFS (Case-Sensitive)
Image Format: read/write disk image
Encryption: none

Save this to say Burn Folder, mount it, copy files. Then insert the blu-ray and drag and drop the dmg for burning. This will preserve the file attributes.