1

In my directory tree, some subfolders contain both *.flac and *.mp3 files, but other subfolders contain only *.mp3 files. I'd like to move all of the *.mp3 files to another destination (a different hard drive) BUT ONLY when a *.flac file is also present in that subdirectory. In other words, I want to leave any *.mp3s when they don't have duplicate *.flacs.

Any suggestions?

1

Summary

An intuitive approach to this problem is to:

  1. recursively iterate over the list of mp3 files,
  2. for each mp3 file found, check for the matching flac file,
  3. if the flac file exists, move the pair of files from the source directory to the corresponding path in the target directory

I've included basic implementations of this simple algorithm in both Python and Bash.

Python Solution

Here is a Python script that should do what you asked for:

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""move_pairs.py

Move pairs of matching *.mp3 and *.flac files from one directory tree to another.
"""

from glob import glob
import os
import shutil
import sys

# Get source and target directories as command-line arguments
source_dir = sys.argv[1] 
target_dir = sys.argv[2]

# Recursivley iterate over all files in the source directory with a ".mp3" filename-extension
for mp3_file in glob("{}/**/*.mp3".format(source_dir), recursive=True):

    # Create the corresponding ".flac" filename
    flac_file = mp3_file[:-3] + "flac"

    # Check to see if the ".flac" file exists - if so, then proceed
    if os.path.exists(flac_file):

        # Create the pair of target paths
        new_mp3_path = target_dir + "/" + mp3_file.partition("/")[2]
        new_flac_path = target_dir + "/" + flac_file.partition("/")[2]

        # Ensure that the target subdirectory exists
        os.makedirs(os.path.dirname(new_mp3_path), exist_ok=True)

        # Move the files
        shutil.move(mp3_file, new_mp3_path)
        shutil.move(flac_file, new_flac_path)

You could invoke it like this:

python move_pairs.py source-directory target-directory

To test it out, I created the following file hierarchy:

.
├── source_dir
│   ├── dir1
│   │   ├── file1.flac
│   │   ├── file1.mp3
│   │   └── file2.mp3
│   └── dir2
│       ├── file3.flac
│       ├── file3.mp3
│       └── file4.mp3
└── target_dir

After running the script, I ended up with the following result:

.
├── source_dir
│   ├── dir1
│   │   └── file2.mp3
│   └── dir2
│       └── file4.mp3
└── target_dir
    ├── dir1
    │   ├── file1.flac
    │   └── file1.mp3
    └── dir2
        ├── file3.flac
        └── file3.mp3

Bash Solution

Here is an almost identical implementation in Bash:

#!//usr/bin/env bash

# Set globstar shell option to enable recursive globbing
shopt -s globstar

# Get source and target directories as command-line arguments
source_dir="$1"
target_dir="$2"

# Recursively iterate over all files in the source directory with a ".mp3" filename-extension
for mp3_file in "${source_dir}"/**/*.mp3; do 

    # Create the corresponding ".flac" filename
    flac_file="${mp3_file%.mp3}.flac"

    # Check to see if the ".flac" file exists - if so, then proceed
    if [[ -f "${flac_file}" ]]; then

        # Create the pair of target paths
    new_mp3_path="${mp3_file/#${source_dir}/${target_dir}}"
    new_flac_path="${flac_file/#${source_dir}/${target_dir}}"

    # Ensure that the target subdirectory exists
    mkdir -p "$(dirname ${new_mp3_path})"

        # Move the files
    mv -i "${mp3_file}" "${new_mp3_path}"
    mv -i "${flac_file}" "${new_flac_path}"

    fi
done

I ran this script as follows:

bash move_pairs.sh source_dir target_dir

This gave the same result as running the Python script.

0

Problem is somewhat simpler if you consider the equivalent: for each FLAC file, move the like-named MP3:

shopt -s globstar

targetroot='/path/to/target'
for f in **/*.flac
do 
    dir=$(dirname "$f")
    mp3=$(basename "$f" .flac).mp3
    [[ -e "$dir/$mp3" ]] || continue
    mkdir -p "$targetroot/$dir"
    mv -t "$targetroot/$dir" "$dir/$mp3"
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.