SetFileTime.psm1

<#
.SYNOPSIS
Set the last access and modification time of a file.
 
.DESCRIPTION
Similar to the touch bash command, Set-FileTime will optionally change access/modified timestamp of a file or directory. If file does not exist, it will be created as an empty file.
 
.PARAMETER $Path
Can use pipeline variables with Path or Name property, to indicate which file/directory to touch.
 
.PARAMETER $Time
DateTime to use for timestamp updates, defaults to current time.
 
.PARAMETER $OnlySetModificationTime
If this switch is used, updates will only be made to the last modified timestamp.
 
.PARAMETER $OnlySetAccessTime
If this switch is used, updates will only be made to the last accessed timestamp.
 
.PARAMETER $NoCreate
If this switch is used, no new files will be created.
 
.EXAMPLE
Set-FileTime sample.txt
 
.EXAMPLE
Get-ChildItem | Set-FileTime
#>
 
function Set-FileTime {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true)][alias("Name")][string]$Path,
        [datetime]$Time = "0001-01-01",
        [switch]$OnlySetModificationTime,
        [switch]$OnlySetAccessTime,
        [switch]$NoCreate
    )

    begin {
        function updateFileSystemInfo {
            param([System.IO.FileSystemInfo]$fsInfo)
            
            $datetime = Get-Date
            if ($Time -ne (Get-Date 0001-01-01)) {
                $datetime = $Time
            }

            if ($OnlySetAccessTime) {
                $fsInfo.LastAccessTime = $datetime
            } elseif ($OnlySetModificationTime) {
                $fsInfo.LastWriteTime = $datetime
            } else {
                $fsInfo.LastWriteTime = $datetime
                $fsInfo.LastAccessTime = $datetime
            }
        }
   
        function touchExistingFile {
            param([string]$arg)

            $resolvedPaths = Resolve-Path $arg
            foreach ($rpath in $resolvedPaths) {
                if (!$rpath) { continue; }
        
               $realPath = $rpath.ProviderPath # So we can also work with UNC paths
                if (Test-Path -type Container $realPath) {
                    $fsInfo = New-Object System.IO.DirectoryInfo($realPath)
                } elseif (Test-Path -IsValid $realPath) {
                    $fsInfo = New-Object System.IO.FileInfo($realPath)
                }
                updateFileSystemInfo($fsInfo)
            }
        }
    }
 
    process {
        if ($path) {
            if (Test-Path $path) {
                if ($PSCmdlet.ShouldProcess($path, "Modify filesystem time attributes")) {
                    touchExistingFile($path)
                }
            } elseif ($NoCreate -eq $false) {
                if ($PSCmdlet.ShouldProcess($path, "Create empty file")) {
                       Set-Content -Path $path -value $null
                }
            }
        }
    }
 
    end { }
}

Set-Alias touch Set-FileTime
Export-ModuleMember -Function Set-FileTime -Alias touch