Python から PowerShell を呼び出して、『ファイルとフォルダ』の『作成日時・更新日時・アクセス日時』を変更するコード例です。
フォルダを指定して、その中にある『ファイルとフォルダ』の『タイムスタンプ』を、一括で変更します。
※ PowerShell を使わずに、Python の外部ライブラリで変更する方法は、『ファイルとフォルダのタイムスタンプを変更するコード例』に書きました。
タイムスタンプの変更方法
Python のサブプロセスラン subprocess.run(cmd) から、PowerShell を呼び出して、タイムスタンプを変更します。
以下は、コマンドラインから PowerShell を起動して、普通にタイムスタンプを変更するコマンド例です。
F:\apps\data>PowerShell -Version 5.1
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS F:\apps\data> Get-ChildItem -LiteralPath F:\\apps\\data -Recurse -Force | ForEach-Object { Set-ItemProperty -LiteralPath $_.FullName -Name Attributes -Value Normal ; Set-ItemProperty -LiteralPath $_.FullName -Name CreationTime -Value "2017/01/02 03:04:05" ; Set-ItemProperty -LiteralPath $_.FullName -Name LastWriteTime -Value "2018/01/02 03:04:05" ; Set-ItemProperty -LiteralPath $_.FullName -Name LastAccessTime -Value "2019/01/02 03:04:05" ; }
これと同じことを、Python で指示して、実行するアプローチになります。
『作成日時・更新日時・アクセス日時』を変更するための PowerShell コマンドは、コマンドライン文字列のリスト (cmd) として、用意します。
cmd は、Python のリスト (list) です。タプル (tuple) を使っても OK でした。
cmd の中に『タイムスタンプを変更する PowerShell コマンド』を書きます。
これを subprocess.run(cmd) に渡して実行することで、ファイルとフォルダのタイムスタンプを変更することができました。
Python マニュアル
コード例で使用した Python 機能のマニュアルの場所です。
(Python) class subprocess.CompletedProcess
コンプリーテッドプロセス(args, returncode, stdout, stderr などが取得できる)
(Python) class pathlib.Path(*pathsegments)
(Python) Path.glob(pattern)
グロブ
(Python) Path.stat()
スタット
(Python) class os.stat_result
スタットリザルト(st_atime, st_mtime, st_ctime の説明)
(Python) classmethod datetime.fromtimestamp(timestamp, tz=None)
r から始まる文字列 r''
は、 raw strings と呼ばれるもの。
f から始まる文字列 f''
は、f-string とか、フォーマット済み文字列リテラル とか呼ばれるもの。
(Python) print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
PowerShell マニュアル
使用した PowerShell コマンドのマニュアルの場所です。
(docs.microsoft.com) Microsoft Docs ⇒ PowerShell ⇒ Overview
(docs.microsoft.com) About PowerShell.exe (バージョンを指定して起動するための -Version の説明など)
(docs.microsoft.com) Get-ChildItem ゲットチャイルドアイテム
(docs.microsoft.com) Get-ChildItem ⇒ Parameters (Directory, File, Hidden, ReadOnly, -LiteralPath, -Recurse, -Force, などの説明)
(docs.microsoft.com) ForEach-Object フォーイーチオブジェクト
(docs.microsoft.com) ForEach-Object ⇒ Description (変数 $_
ダラーアンダースコア、ドルサインアンダースコアの説明)
(docs.microsoft.com) Set-ItemProperty セットアイテムプロパティ
(docs.microsoft.com) Set-ItemProperty ⇒ Examples (読み取り専用属性 IsReadOnly の設定例など)
(docs.microsoft.com) Set-ItemProperty ⇒ Parameters (-LiteralPath, -Name, -Value などの説明)
(docs.microsoft.com) About PowerShell Editions ($PSVersionTable の説明)
.NET マニュアル
PowerShell コマンドの中で使用した名前(FullName, Attributes, CreationTime, LastWriteTime, LastAccessTime, IsReadOnly など)のマニュアルの場所です。
これらは、.NET のマニュアルの中にありました。
(docs.microsoft.com) Microsoft Docs ⇒ .NET ⇒ .NET Core API reference ⇒ System.IO Namespace
(docs.microsoft.com) FileInfo Class ファイルインフォ
(docs.microsoft.com) FileInfo Class ⇒ Properties (FullName, Attributes, CreationTime, LastWriteTime, LastAccessTime, IsReadOnly などの説明)
(docs.microsoft.com) DirectoryInfo Class ディレクトリインフォ
(docs.microsoft.com) DirectoryInfo Class ⇒ Properties (FullName, Attributes, CreationTime, LastWriteTime, LastAccessTime などの説明)
コード例
『ファイルとフォルダ』のタイムスタンプを変更する Python コード例です。
PowerShell の機能を使って、『作成日時・更新日時・アクセス日時』を変更します。
フォルダパスを指定して、その中にある『ファイルとフォルダ』の両方のタイムスタンプを、すべて変更します。
『読み取り専用属性』は、タイムスタンプ変更の妨げになったので、解除コマンドを入れています。ついでに、『隠しファイル属性』も解除しています。
『$_.FullName』には、『ファイルパス または フォルダパス』が、自動的に入ります。
$_
の読み方は、ダラーアンダースコアでした。YouTube で、そう呼んでいる方を見かけました。ドルサインアンダースコアでもいいと思います。
これは、『ForEach-Object』の変数『$_』が持っている『FullName』プロパティを参照しています。
"""
ファイルとフォルダのタイムスタンプを変更するコード例。
Python から Windows の PowerShell を呼び出して、
ファイルとフォルダの作成日時、更新日時、アクセス日時を
変更します。
"""
import subprocess
print('Start')
# (1/4) フォルダを決めます。
data_dir = r'F:\apps\data'
# (2/4) 日時を決めます。
creation_time = '"2017/01/02 03:04:05"' # 作成
last_write_time = '"2018/01/02 03:04:05"' # 更新
last_access_time = '"2019/01/02 03:04:05"' # アクセス
# (3/4) PowerShellのコマンドを決めます。
cmd = [
# PowerShellを指定 (PowerShell 5.1)
'PowerShell', '-Version', '5.1',
# フォルダを指定
'Get-ChildItem',
'-LiteralPath', data_dir, # 日時変更の対象フォルダ
'-Recurse', # フォルダのフォルダも変更対象にする
'-Force', # 隠しファイルも変更対象にする
# Get-ChildItem の結果を ForEach-Object に渡すための記号
'|',
# フォルダの中のファイルとフォルダを、1つずつたどる。
'ForEach-Object',
'{',
# 読み取り専用属性と隠しファイル属性を外す
'Set-ItemProperty',
'-LiteralPath', '$_.FullName',
'-Name', 'Attributes',
'-Value', 'Normal',
';',
# 作成日時 (ctime) 変更
'Set-ItemProperty',
'-LiteralPath', '$_.FullName',
'-Name', 'CreationTime',
'-Value', creation_time,
';',
# 更新日時 (mtime) 変更
'Set-ItemProperty',
'-LiteralPath', '$_.FullName',
'-Name', 'LastWriteTime',
'-Value', last_write_time,
';',
# アクセス日時 (atime) 変更
'Set-ItemProperty',
'-LiteralPath', '$_.FullName',
'-Name', 'LastAccessTime',
'-Value', last_access_time,
';',
'}',
# (デバッグ) PowerShellのバージョンを表示する
';',
'$PSVersionTable',
] # cmd ここまで
# (4/4) 実行します。
cp = subprocess.run(cmd)
print('End')
# 以上です。
# 以下は、デバッグ用のコードです。
print('\nStart Debug')
# (デバッグ1) 変更結果を確認します。
import pathlib
import datetime
data_dir_path = pathlib.Path(data_dir)
print('\n(デバッグ1) 変更結果を確認する')
print('名前 - 作成日時 - 更新日時 - アクセス日時')
for p in data_dir_path.glob('**/*'):
stat = p.stat()
ctime = datetime.datetime.fromtimestamp(stat.st_ctime)
mtime = datetime.datetime.fromtimestamp(stat.st_mtime)
atime = datetime.datetime.fromtimestamp(stat.st_atime)
print(f'{p.name} - {ctime} - {mtime} - {atime}')
# (デバッグ2) subprocess.run の戻り値を見ます。
print('\n(デバッグ2) subprocess.run の戻り値を見る')
print(f'cp = subprocess.run(cmd)')
print(f'cp.returncode: {cp.returncode}')
print('cp.args: %s' % '\n '.join(cp.args))
# cp: CompletedProcess の略です。
print('\nEnd Debug')
実行結果
Python コードの実行結果です。
『ファイルとフォルダ』の『作成日時・更新日時・アクセス日時』を、すべて変更することができました。
タイムスタンプの変更中は、とくに何も表示されませんでした。
実行結果で表示されたものは、デバッグのために書いた情報だけでした。
Start
Name Value
---- -----
PSVersion 5.1.14409.1018
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14409.1018
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
End
Start Debug
(デバッグ1) 変更結果を確認する
名前 - 作成日時 - 更新日時 - アクセス日時
memo-01.pdf - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-02.docx - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-03.xlsx - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-04.pptx - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-05.txt - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-06.csv - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-07.odt - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-08.ods - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-09.odp - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-10.html - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-11.css - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
memo-12.js - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
photos - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
image-01.jpg - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
image-02.png - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
image-03.gif - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
image-04.bmp - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
image-05.webp - 2017-01-02 03:04:05 - 2018-01-02 03:04:05 - 2019-01-02 03:04:05
(デバッグ2) subprocess.run の戻り値を見る
cp = subprocess.run(cmd)
cp.returncode: 0
cp.args: PowerShell
-Version
5.1
Get-ChildItem
-LiteralPath
F:\apps\data
-Recurse
-Force
|
ForEach-Object
{
Set-ItemProperty
-LiteralPath
$_.FullName
-Name
Attributes
-Value
Normal
;
Set-ItemProperty
-LiteralPath
$_.FullName
-Name
CreationTime
-Value
"2017/01/02 03:04:05"
;
Set-ItemProperty
-LiteralPath
$_.FullName
-Name
LastWriteTime
-Value
"2018/01/02 03:04:05"
;
Set-ItemProperty
-LiteralPath
$_.FullName
-Name
LastAccessTime
-Value
"2019/01/02 03:04:05"
;
}
;
$PSVersionTable
End Debug
変更結果の画像
タイムスタンプ変更前
すべてのファイルには、『読み取り専用属性』が付いていました。
photos フォルダの中には、さらに、画像ファイルの image-01.jpg ~ image-05.webp が入っていました。
また、photo フォルダと、その中のファイルには、『隠しファイル属性』が付いていました。
変更後
ファイルのプロパティ
意図した通り、フォルダの中にある『ファイルとフォルダ』の『作成日時・更新日時・アクセス日時』を、すべて変更することができました。
自分の場合は、『読み取り専用属性』と『隠しファイル属性』が不要でした。
なので、コード例では、それらを外すために -Name Attributes で -Value Normal を指定しました。
以上です。