tech.guitarrapc.cóm

Technical updates

PowerShell で touch コマンドをしたい

Linux には touch コマンドがあります。
  1. アクセス時刻と更新時刻を現在(あるいは任意)の時刻に変更
  2. ファイルがない場合は空ファイルの生成
Windows で、バッチでやろうというのを見かけるのですが苦しいので PowerShell でサクリと。

MS-DOSコマンドで更新時間の更新

このような感じで出来ます。
Updating the Date and Time Stamps on Files
COPY /B EXAMPLE +,,

PowerShellで更新時間の更新

PowerShell ならもっと自在に行えます。 この場合は、 Set-ItemProperty が適当でしょうか。
Set-ItemProperty -Path D:\test.log -Name LastAccessTime -Value $(Get-Date)
これで現在時刻にd:\text.log の更新時刻が修正されます。

touch Cmdlet を作成してみる

Linuxのコマンド概要を参考に、touchコマンドレットを作成してみます。
【 touch 】 ファイルのタイム・スタンプを変更する
function touch{
    [CmdletBinding()]
    param(
        [parameter(
        position = 0,
        mandatory = 1,
        ValueFromPipeline = 1,
        ValueFromPipelineByPropertyName = 1
        )]
        [string]$path,

        [parameter(
        position = 1,
        mandatory = 0,
        ValueFromPipeline = 1,
        ValueFromPipelineByPropertyName = 1
        )]
        [datetime]$date = $(Get-Date),

        [parameter(
        position = 2,
        mandatory = 0,
        HelpMessage = "Change Last AccessTime only"
        )]
        [switch]$access,

        [parameter(
        position = 3,
        mandatory = 0,
        HelpMessage = "Do not create file if not exist"
        )]
        [switch]$nocreate,

        [parameter(
        position = 4,
        mandatory = 0,
        HelpMessage = "Change Last WriteTime only"
        )]
        [switch]$modify,

        [parameter(
        position = 5,
        mandatory = 0,
        HelpMessage = "LastAccessTime reference file"
        )]
        [string]$reference
    )

    if (-not(Test-Path $path))
    {
        if ((!$nocreate))
        {
            New-Item -Path $path -ItemType file -Force
        }
    }
    else
    {
        try
        {
            if ($reference)
            {
                $date = (Get-ItemProperty -Path $reference).LastAccessTime
            }

            if ($access)
            {
                Get-ChildItem $path | %{Set-ItemProperty -path $_.FullName -Name LastAccessTime -Value $date -Force -ErrorAction Stop}
            }

            if ($modify)
            {
                Get-ChildItem $path | %{Set-ItemProperty -path $_.FullName -Name LastWriteTime -Value $date -Force -ErrorAction Stop}
            }

            if (!$access -and !$modify)
            {
                Get-ChildItem $path | %{Set-ItemProperty -path $_.FullName -Name LastAccessTime -Value $date -Force -ErrorAction Stop}
                Get-ChildItem $path | %{Set-ItemProperty -path $_.FullName -Name LastWriteTime -Value $date -Force -ErrorAction Stop}
            }
        }
        catch
        {
            throw $_
        }
        finally
        {
            Get-ChildItem $path | %{Get-ItemProperty -Path $_.FullName | select Fullname, LastAccessTime, LastWriteTime}
        }
    }

}

使用方法

そのままなのですが一応。 ファイルが存在しない場合に新規空ファイルを作成
PS D:\> touch -path d:\test\hoge.log

    Directory: D:\test

Mode         LastWriteTime Length Name
----         ------------- ------ ----
-a--- 2013/08/19      9:54      0 hoge.log
ファイルが存在しない場合でも新規ファイルを作らない場合は、-nocreate スイッチを付けます。
touch -path d:\test\hoge.log -nocreate
ファイルが存在した状態でそのまま実行すると、LastWriteTime と LastAccessTimeが更新します。
touch -path d:\test\hoge.log

FullName         LastAccessTime      LastWriteTime
--------         --------------      -------------
D:\test\hoge.log 2013/08/19 10:00:01 2013/08/19 10:00:01
-modify と -access スイッチを付けると 明示的にLastWriteTime と LastAccessTime の両方が更新されます。
touch -path d:\test\hoge.log -modify -access

FullName         LastAccessTime      LastWriteTime
--------         --------------      -------------
D:\test\hoge.log 2013/08/19 10:00:02 2013/08/19 10:00:02
-access スイッチ のみを付けると、 LastAccessTime が更新されます。
touch -path d:\test\hoge.log -access

FullName         LastAccessTime      LastWriteTime
--------         --------------      -------------
D:\test\hoge.log 2013/08/19 10:00:59 2013/08/19 10:00:01
-modify スイッチ のみを付けると、 LastWriteTime が更新されます。
touch -path d:\test\hoge.log -modify

FullName         LastAccessTime      LastWriteTime
--------         --------------      -------------
D:\test\hoge.log 2013/08/19 10:00:59 2013/08/19 10:01:53
-reference パラメータに、参照元のファイルを指定すると、そのファイルの内容に沿って更新します。 更新内容は、access や modify スイッチに依存します。
touch -path d:\test\hoge.log -modify -access -reference C:\bootmgr

FullName         LastAccessTime      LastWriteTime
--------         --------------      -------------
D:\test\hoge.log 2012/07/26 20:47:56 2012/07/26 20:47:56
path に * を指定すれば、そのフォルダのアイテム全てが更新されます。
touch -path d:\test\* -modify -access -reference C:\bootmgr

FullName             LastAccessTime      LastWriteTime
--------             --------------      -------------
D:\test\hoge.log     2012/07/26 20:47:56 2012/07/26 20:47:56
D:\test\hogefuga.log 2012/07/26 20:47:56 2012/07/26 20:47:56

まとめ

本家touch と完全に同一かと言われるとどうなのという感じですが、おおよそこういった感じでしょうか。 よろしければご利用ください。
https://github.com/guitarrapc/PowerShellUtil/tree/master/LinuxCommand