Niraj Zade   Home  Blog  Tools 

Figure out songs deleted on laptop and phone

Tags: everyday engineering  

Introduction to the problem

I maintain and use a curated music library of a few thousand songs.

This library is synced to my laptop as well as to my phone. Currently, I am in the trimming phase - I am deleting songs that I don't like much.

The problem is that sometimes I delete songs on the laptop, and sometimes I delete songs on phone.

Every Sunday, I take a master backup of data. This includes my song library. At this point, I have to:

  1. Figure out the songs that I deleted on laptop
  2. Figure out the songs that I deleted on phone
  3. Finally, figure out the songs that survived the filtering.
  4. Backup the songs that survived the filtering.

This is hard to do manually. But, this problem is very easy to solve through some code.

The Venn diagram looks like this:

Solution

It is simple:

Copy songs on phone to a directory. Then run a script to:

  1. Create a dictionary of songs on laptop
  2. Create a dictionary of songs on phone
  3. Find intersection of songs in both collections (songs to keep)
  4. Copy the songs to keep into a dedicated songs_to_keep directory

It is simple. And doable.

from pathlib import Path
import shutil
import os

laptop_music_dir = Path("/home/user/data/music/laptop_mp3")
phone_music_dir = Path("/home/user/data/music/phone_mp3")
music_to_keep_dir = Path("/home/user/data/music/music_to_keep")

laptop_music_dict = {}
phone_music_dict = {}
music_to_keep_dict = {}

# mp3
laptop_music_path_list = list(laptop_music_dir.rglob("*.mp3"))
phone_music_path_list = list(phone_music_dir.rglob("*.mp3"))


for laptop_song_path in laptop_music_path_list:
    laptop_music_dict[laptop_song_path.stem] = str(laptop_song_path)
for phone_song_path in phone_music_path_list:
    phone_music_dict[phone_song_path.stem] = str(phone_song_path)


# find set intersection, and store it into music_to_keep_dict
for key in laptop_music_dict:
    if key in phone_music_dict:
        music_to_keep_dict[key] = laptop_music_dict[key]



# delete music_to_keep directory if it already exists
if os.path.exists(music_to_keep_dir) and os.path.isdir(music_to_keep_dir):
        shutil.rmtree(music_to_keep_dir)
# create directory
Path(music_to_keep_dir).mkdir(parents=True, exist_ok=True)

for song_key in music_to_keep_dict:
    source_path = music_to_keep_dict[song_key]
    parent_dir_name = Path(music_to_keep_dict[song_key]).resolve().parents[0].name
    # create parent dir if it doesn't exist
    Path(music_to_keep_dir / parent_dir_name).mkdir(parents=True, exist_ok=True)
    # copy song, maintain directory hierarchy
    destination_path = music_to_keep_dir / parent_dir_name / f"{song_key}.mp3"
    shutil.copy2(src=str(source_path), dst=str(destination_path))
    print(f"copied {song_key} to {str(destination_path)}")
print("done")

Makefile

SHELL = /bin/bash

find-music-intersection:
        python3 intersection_finder.py;

Now, I have simply added make find-music-intersection into my backup script.

That's it. Another daily life problem solved through some programming.

Programming is a superpower.