『退屈なことはPythonにやらせよう』10章 ファイル管理のらくがき帳📝
こんにちは。aliceです。
休日の朝にベーコンとがエッグとか聞くと、モーニングしたいなぁと思うのはなぜでしょう。
ちょっと優雅な気分になります🥖
今回は『退屈なことは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を見すぎておなかがすいてきたので朝ごはんにします。
この記事が気に入ったらサポートをしてみませんか?