見出し画像

『退屈なことはPythonにやらせよう』10章 ファイル管理のらくがき帳📝

こんにちは。aliceです。
休日の朝にベーコンとがエッグとか聞くと、モーニングしたいなぁと思うのはなぜでしょう。
ちょっと優雅な気分になります🥖

baconとegg🥚


今回は『退屈なことはPythonにやらせよう』10章 ファイル管理のらくがき帳です。

今週やったはずなのに、もはや記憶がありません🤣
まぁ、しょうがないですねー。
そんなときのためのらくがき帳ですねー。


前回のらくがき帳📝


では、以下らくがきです。



10章 英語版🔤


GitHub💖


10.1.4 send2trashモジュールを用いて安全に削除する


send2trashモジュールを使うと、完全に削除するのではなくゴミ箱に移動します。
「うっかり消しちゃったー😭」ということがたびたびあるので、ありがたしです。

from pathlib import Path

import send2trash

file = Path('file_path')
send2trash.send2trash(file)
print('ファイルをゴミ箱に移動しました。')


ごみ箱にいらっしゃる。



10.2 ディレクトリツリーを渡り歩く


pathlibモジュールでディレクトリツリーを歩いてみましたー。
globメソッドが大活躍ですね。

import glob
from pathlib import Path

base_path = Path('folder_path')

for folder_name in glob.glob(str(base_path / '**'), recursive=True):  # 再帰的にフォルダを検索
    folder_path = Path(folder_name)
    if folder_path.is_dir():
        print('The current folder is ' + folder_path.as_posix())

    for sub_folder in folder_path.glob('*'):
        if sub_folder.is_dir():
            print('SUBFOLDER OF ' + folder_path.as_posix() + ': ' + sub_folder.name)

    for filename in folder_path.glob('*.*'):
        if filename.is_file():
            print('FILE INSIDE ' + folder_path.as_posix() + ': ' + filename.name)

    print('')


このように出力されます。


10.4 プロジェクト:米国式日付を欧州式日付に変換する


米国式日付も欧州式日付も使うことはきっとない(と思われる)ので、「2022」を「2023」に変換してみました。
年度を変換するイメージです。

from pathlib import Path


def process_directory(directory_path):
    """
    ディレクトリ内のファイル名に含まれる年を変換する

    :param directory_path: フォルダのパス
    :return:
    """
    path = Path(directory_path)
    for item in path.iterdir():
        if item.is_file():
            new_name = item.name.replace('2022', '2023')
            new_path = item.parent / new_name
            item.rename(new_path)
        elif item.is_dir():
            process_directory(item)


if __name__ == '__main__':
    target_directory = 'folder_path'
    process_directory(target_directory)
    print('変換が完了しました。')



10.5 プロジェクト:ディレクトリをZIPファイルにバックアップする


ZIPファイルでのバックアップはどうなんだろうと思ったのですが、やってみたら意外に楽しかったです。

import zipfile
from pathlib import Path


def generate_unique_backup_filename(folder, backup_folder):
    """
    バックアップファイル名を生成する関数。

    :param folder: バックアップをとるフォルダ
    :param backup_folder: バックアップ先のフォルダ
    :return:
    """
    folder_name = folder.name
    number = 1
    while True:
        zip_filename = f'{folder_name}_{number}.zip'
        backup_zip_path = backup_folder / zip_filename
        if not backup_zip_path.exists():
            return backup_zip_path
        number += 1


def backup_to_zip(folder, backup_folder):
    """
    バックアップをZIPファイルにする関数。

    :param folder: バックアップをとるフォルダ
    :param backup_folder: バックアップ先のフォルダ
    :return:
    """
    folder = Path(folder).resolve()
    backup_folder = Path(backup_folder).resolve()

    backup_zip_path = generate_unique_backup_filename(folder, backup_folder)

    # ZIPファイルを作成。
    print(f'{backup_zip_path.name} を作成中...')
    with zipfile.ZipFile(backup_zip_path, 'w') as backup_zip:
        # フォルダ内のすべてのフォルダとファイルをバックアップ。
        for item in folder.glob('**/*'):
            print(f'追加中: {item}')
            arcname = item.relative_to(folder)
            backup_zip.write(item, arcname=arcname)

    print('完了。')


if __name__ == '__main__':
    source_folder = folder_path' # バックアップをとるフォルダ
    backup_destination = 'folder_path' # バックアップ先のフォルダ
    backup_to_zip(source_folder, backup_destination)


バックアップを取るごとに、番号が増えていくのが楽しい✨


10.8 演習プロジェクト

10.8.1 選択コピー

ディレクトリツリーを渡り歩いて、.pdfや.jpgなどの特定の拡張子を持つファイルを見つけ、新しいディレクトリにコピーしましょう。

今回はテキストファイルを探してみました。

import shutil
from pathlib import Path


def copy_files_with_extension(source_dir, destination_dir, extension):
    # コピー先のディレクトリが存在しなければ作成
    if not destination_dir.exists():
        destination_dir.mkdir()

    # コピー元のディレクトリを再帰的に探索
    for filename in source_dir.rglob('*' + extension):
        # コピー先のディレクトリにコピー
        shutil.copy(filename, destination_dir)
        print(f'コピー完了: {filename}')


if __name__ == "__main__":
    # ファイルの拡張子を指定
    extension = '.txt'

    path = 'folder_path'

    # コピー先のディレクトリを指定
    copy_to_dir = Path(path) / 'new_folder'

    # コピー元のディレクトリを指定
    copy_from_dir = Path(path) / 'sample'

    copy_files_with_extension(copy_from_dir, copy_to_dir, extension)

    print('すべてのファイルのコピーが完了しました。')


spamとbaconとeggが空腹には響きます。
おなかがすいてきますね。


10.8.2 巨大なファイルを探す

ディレクトリツリーを渡り歩いて、大きなファイルを探し出すプログラムを書きましょう。

そんな大きなファイルがなかったので、1MB以上のファイルを探してみました。

from pathlib import Path

# 最小ファイルサイズ(1MB = 1024 * 1024バイト)
min_file_size = 1024 * 1024


def find_large_files(start_dir):
    start_path = Path(start_dir)

    for file_path in start_path.rglob('*'):
        if file_path.is_file() and file_path.stat().st_size > min_file_size:
            size_mb = file_path.stat().st_size / (1024 * 1024)
            print(f'大きなファイルを発見🗽: {file_path} (サイズ: {size_mb:.2f} MB)')


if __name__ == '__main__':
    path_to_search = 'folder_path'
    find_large_files(path_to_search)


無事に大きなファイルを発見しました🗽


10.8.3 連番の飛びを埋める

1つのディレクトリの中で、spam001.txt、spam002.txtなどの、指定した接頭辞を持つ連番ファイルを探し出し、連番がかけている場所を探しだすプログラムを書きましょう。

import re
from pathlib import Path


def find_missing_sequence_numbers(prefix, directory):
    """
    ファイル名がprefixで始まる連番のファイルがdirectoryに存在するか調べる

    :param prefix: ファイル名の接頭辞
    :param directory: フォルダのパス
    :return:
    """
    directory_path = Path(directory)
    pattern = re.compile(rf'{re.escape(prefix)}(\d+).docx')
    existing_numbers = set()

    for file_path in directory_path.glob(f'{prefix}*'):
        match = pattern.match(file_path.name)
        if match:
            number = int(match.group(1))
            existing_numbers.add(number)

    if not existing_numbers:
        return []

    max_number = max(existing_numbers)
    missing_numbers = set(range(1, max_number + 1)) - existing_numbers

    return sorted(list(missing_numbers))


if __name__ == '__main__':
    prefix = 'egg'
    directory_path = Path('folder_path')

    missing_numbers = find_missing_sequence_numbers(prefix, directory_path)

    if missing_numbers:
        print('欠けている連番:')
        print(missing_numbers)
    else:
        print('欠けている連番はありません。')


003が抜けています。


3番が抜けていると教えてくれました。


ファイル管理はやりたいことがたくさんあるので楽しいですね。
ずっと遊べそうです。


spam、egg、baconを見すぎておなかがすいてきたので朝ごはんにします。


この記事が気に入ったらサポートをしてみませんか?