最新n個のファイルをコピーする
Windowsで,あるディレクトリにあるファイルを,新しい順にn個,別のディレクトリにコピーしたい.GUIでやるならエクスプローラからファイルを日付でソートし,上からn個選んでコピーすれば良いのだけれど,自動でやろうとすると少し面倒である.
バッチファイルだけでは荷が重そうなので,Pythonを使う.
- Windows 10
- Python 3
ディレクトリ構成
以下のような構成で,ファイルの新旧は(古い←) a b c d e f (→新しい)とする.C:\src
から新しい順に3つf,e,dをC:/dest
にコピーしたい.
C:/
├ src/
│ ├ dir1
│ │ ├ b.txt
│ │ ├ d.txt
│ │ └ f.txt
│ ├ a.txt
│ ├ c.txt
│ └ e.txt
└ dest/
特定のディレクトリにあるファイルの一覧
特定のディレクトリにあるファイルの一覧は,pathlibで取得できる.
import pathlib
path_name_from = "C:\src"
# srcディレクトリのPathオブジェクト
path = pathlib.Path(src_path_name)
assert path.is_dir() # 指定されたパスがディレクトリではない時はエラー
# path以下の全てのファイルとディレクトリ
files = list(path.glob("**/*"))
for f in files:
print(f)
出力は以下の通り.
C:\src\a.txt
C:\src\c.txt
C:\src\dir1
C:\src\e.txt
C:\src\dir1\b.txt
C:\src\dir1\d.txt
C:\src\dir1\f.txt
ファイルを抽出
取得したfiles
は,ファイルとディレクトリが混じった状態になっている.ここから,ファイルだけを抽出する.
# 指定したパスがファイルかどうか判定する関数
def is_file(path):
return path.is_file()
# is_file()が真のパスのみ抽出
files = list(filter(is_file, files))
for f in files:
print(f)
出力は以下の通り.
C:\src\a.txt
C:\src\c.txt
C:\src\e.txt
C:\src\dir1\b.txt
C:\src\dir1\d.txt
C:\src\dir1\f.txt
作成日時によるソート
Path.stat()
でos.stat_resultが取得でき,そこから以下の情報を参照できる.
- st_atime: 最終アクセス時刻 (sec)
- st_mtime: 最終内容更新時刻 (sec)
- st_ctime: 作成時刻 (sec)
これを用いて,files
を最終内容更新時刻でソートする.
def modified_time(path):
return path.stat().st_mtime
# 更新日時でソート
files.sort(key=modified_time, reverse=True)
for f in files:
print(f)
新しい順に使いたいので,降順ソート(reverse)しておいた.出力は以下の通り.
C:\src\dir1\f.txt
C:\src\e.txt
C:\src\dir1\d.txt
C:\src\c.txt
C:\src\dir1\b.txt
C:\src\a.txt
copyコマンド
Python上から,Windowsのcopyコマンドを実行する.ここでは,subprocess.run()を使う.
import subprocess
path_name_to = "C:\dest"
N_MAX_COPY = 3
n_copy = min(N_MAX_COPY, len(files)) # コピーするファイルの数は,コピーしたいフ
# ァイルの数とディレクトリに存在するファイ
# ルの数の小さい方.
for i in range(n_copy):
subprocess.run(
"copy" +
" \"" + str(files[i]) + "\"" +
" \"" + path_name_to + "\"", shell=True)
最新n個のファイルをコピーするスクリプト
以上をまとめると,path_name_from
からpath_name_to
に最新n個のファイルをコピーするには以下のようにする.
import pathlib
import subprocess
def main():
path_name_from = "C:\\src"
path_name_to = "C:\\dest"
N_MAX_COPY = 3
# srcディレクトリのPathオブジェクト
path = pathlib.Path(path_name_from)
assert path.is_dir() # 指定されたパスがディレクトリではない時はエラー
# path以下の全てのファイルとディレクトリ
files = list(path.glob("**/*"))
# ディレクトリは除外
files = list(filter(is_file, files))
# 更新日時でソート
files.sort(key=modified_time, reverse=True)
# 出力する数
n_export = min(len(files), N_MAX_COPY)
# destディレクトリに同期候補をコピー
for i in range(n_export):
subprocess.run(
"copy" +
" \"" + str(files[i]) + "\"" +
" \"" + path_name_to + "\"", shell=True)
return
def is_file(path):
return path.is_file()
def modified_time(path):
return path.stat().st_mtime
if __name__ == "__main__": main()
あとがき
ローカルにある写真フォルダから,最近撮ったものを抽出してクラウドストレージに同期しておきたかった.写真は,基本的にはローカルのアーカイブにあれば十分なのだけれど,新しいファイルは時々スマホなどから確認したくなる場合がある.