일반화하다

일반화하다

내 디렉터리 트리에서 일부 하위 폴더에는 *.flac 및 *.mp3 파일이 모두 포함되어 있지만 다른 하위 폴더에는 *.mp3 파일만 포함되어 있습니다. 모든 *.mp3 파일을 다른 대상(다른 하드 드라이브)으로 이동하고 싶지만 *.flac 파일이 해당 하위 디렉터리에도 있는 경우에만 가능합니다. 즉, *.flac의 중복이 없을 때 *.mp3를 유지하고 싶습니다.

어떤 제안이 있으십니까?

답변1

일반화하다

이 문제를 해결하는 직관적인 방법은 다음과 같습니다.

  1. mp3 파일 목록을 반복적으로 반복합니다.
  2. 발견된 각 mp3 파일에 대해 일치하는 flac 파일을 확인하고,
  3. flac 파일이 존재하는 경우 파일 쌍을 소스 디렉터리에서 대상 디렉터리의 해당 경로로 이동합니다.

저는 이 간단한 알고리즘의 기본 구현을 Python과 Bash에 포함시켰습니다.

파이썬 솔루션

다음은 원하는 작업을 수행하는 Python 스크립트입니다.

#!/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)

다음과 같이 호출할 수 있습니다.

python move_pairs.py source-directory target-directory

테스트하기 위해 다음과 같은 파일 계층 구조를 만들었습니다.

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

스크립트를 실행한 후 다음과 같은 결과를 얻었습니다.

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

쿵쿵 솔루션

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

이 스크립트를 다음과 같이 실행합니다.

bash move_pairs.sh source_dir target_dir

이는 Python 스크립트를 실행하는 것과 동일한 결과를 제공합니다.

답변2

동등성을 고려하면 문제는 약간 더 간단합니다. 각 FLAC 파일에 대해 동일한 이름의 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

관련 정보