複数ファイルの最終更新日時を一括で変更する

Tech Knowledge
公開: 2020-08-24
Article Image

はじめに

カレントフォルダ配下の全ファイルの更新日時を一括で同一日時に設定したい。
再帰的にサブフォルダ内のファイルも対象とする。
PowerShell を使用。

フォルダ配下のファイルを列挙

Get-ChildItem を使用する。
以下のオプションを指定。

  • -Recurse: サブフォルダも含めて再帰的に処理
  • -File: ファイルのみを取得
Get-ChildItem -Recurse -File

列挙したファイルを処理

ForEach-Object を使用。
ForEach-Object は基本的にパイプライン | を経由して使うことが前提のコマンド。

| ForEach-Object { 
    # ここに処理を書く
    # 何行書いてもよい
    # $_ は今処理しているオブジェクト(例:ファイルやフォルダ)
    $_.Name  # 今処理しているオブジェクトの名前を表示
}
  • $_ はパイプライン内で「今処理している要素」を指す
  • ブロック内の最後の式の結果が自動的に出力される(代入は出力されない)
    上の例の場合、ファイル名が出力されることになる。

更新日時の更新

更新日時を更新するには LastWriteTime を設定すればよい。

| ForEach-Object {
    $_.LastWriteTime = [DateTime]'2020-01-01 00:00:00'
}

まとめると

Get-ChildItem -Recurse -File | ForEach-Object {
    $_.LastWriteTime = [DateTime]'2020-01-01 00:00:00'
}

コマンドや引数の省略名を使用すると以下のように書き換えできる。

gci -r -File | % { 
    $_.LastWriteTime = '2020-01-01 00:00:00'
}
  • gci = Get-ChildItem
  • -r = -Recurse
  • % = ForEach-Object
  • 日付は文字列でOK(PowerShell が自動変換する)

ワンライナー

gci -r -File | % { $_.LastWriteTime = '2020-01-01 00:00:00' }

現在日時で更新

Get-Date を使用すればよい。

gci -r -File | % { $_.LastWriteTime = Get-Date }

おまけ

  • テスト用にサブフォルダとファイルを PowerShell で生成
# サブフォルダ数とファイル数の設定
$subfolderCount = 3
$filesPerFolder = 5

# サブフォルダを作成(存在しなければ)
1..$subfolderCount | ForEach-Object {
    $folderName = "SubFolder_$($_)"
    if (-not (Test-Path $folderName)) {
        New-Item -ItemType Directory -Path $folderName | Out-Null
    }
}

# ルートフォルダにもファイルを作る
$targetFolders = @(".") + (Get-ChildItem -Directory | Select-Object -ExpandProperty Name)

foreach ($folder in $targetFolders) {
    1..$filesPerFolder | ForEach-Object {
        $fileName = "file_{0}.txt" -f (Get-Random -Minimum 1000 -Maximum 9999)
        $filePath = Join-Path $folder $fileName
        $content = -join ((65..90) + (97..122) | Get-Random -Count 50 | ForEach-Object {[char]$_})
        Set-Content -Path $filePath -Value $content
    }
}
  • ランダムな更新日時を設定する
gci -r -File | % {
    $daysOffset = Get-Random -Minimum 0 -Maximum 365
    $randomDate = (Get-Date).AddDays(-$daysOffset).AddHours((Get-Random -Minimum 0 -Maximum 24))
    $_.LastWriteTime = $randomDate
    $_.FullName + " -> " + $randomDate
}