Created
December 31, 2013 17:22
-
-
Save lidopaglia/8199868 to your computer and use it in GitHub Desktop.
Change the access and modification times of one or more files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 3.0 | |
<# | |
.SYNOPSIS | |
Change the access and modification times of one or more files. | |
.DESCRIPTION | |
Set-File is designed to work in similar fashion to the Unix 'touch(1)' command. If the given filepath does | |
not exist, Set-File creates the file setting its initial content to $null. If the file already exists then | |
some or all of the file's timestamps can be modified. Unless specific properties are specified an existing | |
file's CreationTime, LastAccessTime, and LastWriteTime properties will be modified. A specific date can be | |
used or a reference file can be provided from which to clone a timestamp from. If neither a date or file | |
is provided the default date is set to the current time. | |
.NOTES | |
Author : Lido Paglia <[email protected]> | |
Date : 12/31/2013 10:18:28 | |
Tags : file, path, touch, date, timestamp | |
Comments : | |
.PARAMETER FilePath | |
One or more files to modify. | |
.PARAMETER Property | |
The specific timestamp property to modify. Properties include LastWriteTime, LastAccessTime, and CreationTime. | |
The default behavior will modify all three properties if a single property is not provided. | |
.PARAMETER Date | |
A specific datetime object to use for modifying one or more file timestamps. If a date is not specified the | |
current time will be used. | |
.PARAMETER ReferenceFile | |
A path to a reference file from which to clone a timestamp from. Similar to -r, --reference=FILE | |
in touch(1). | |
.PARAMETER ReferenceProperty | |
The timestamp to use from the given reference file. This parameter is mandatory if -FileDate is specified. | |
Available options are: LastAccessTime, LastWriteTime, or CreationTime. | |
.PARAMETER PassThru | |
Passes an FileInfo object representing the modified item to the pipeline. By default, this script cmdlet does | |
not generate any output. | |
.PARAMETER Force | |
Allows overwriting an existing read-only file. If the file path specified does not exist using -Force will create the | |
file including any non-existent directories in the specified path. Even using the Force parameter, the cmdlet cannot | |
override filesystem security restrictions. | |
.INPUTS | |
System.String. You can pipe a list of objects to Set-File to operate on. | |
.OUTPUTS | |
None or an object representing the new or changed item. | |
When you use the Passthru parameter, Set-File generates an object representing the modified item. | |
Otherwise, this cmdlet does not generate any output. | |
.EXAMPLE | |
touch .\foo\bar\bat -Force | |
Creates the file 'bat' in the folder path '.\foo\bar' in the current working directory. | |
.EXAMPLE | |
touch -FilePath foo.txt -Date (Get-Date).AddDays(-2) | |
.EXAMPLE | |
Get-ChildItem f* -File | touch -PassThru | |
Gets all files beginning with the letter 'f' in the current working directory and sets their LastWriteTime, | |
LastAccessTime, and CreationTime to the current time and passes their fileinfo objects to the pipeline. | |
.EXAMPLE | |
ls f* -File | touch -Property LastWriteTime -Date (Get-Date 12/20/1990) | |
Gets all files beginning with the letter 'f' in the current working directory and sets their LastWriteTime | |
to the specified date, 12/20/1990 | |
.LINK | |
Set-Content | |
.LINK | |
New-Item | |
.LINK | |
http://en.wikipedia.org/wiki/Touch_(Unix) | |
.LINK | |
http://sushihangover.blogspot.com/2012/10/powershell-true-touch-file-routine.html | |
.LINK | |
http://stackoverflow.com/questions/3038337/powershell-resolve-path-that-might-not-exist | |
#> | |
function Set-File | |
{ | |
[cmdletbinding(SupportsShouldProcess)] | |
Param( | |
[Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName,HelpMessage="Which file to create or modify?")] | |
[Alias("FullName")] | |
[String[]]$FilePath, | |
[ValidateSet("All","LastAccessTime","LastWriteTime","CreationTime")] | |
[String]$Property = "All", | |
[Parameter(ParameterSetName='DateFromArgs')] | |
[DateTime]$Date, | |
[Parameter(ParameterSetName='DateFromFile')] | |
[ValidateScript({Test-Path $_ -PathType Leaf})] | |
[String]$ReferenceFile, | |
[Parameter(Mandatory,ParameterSetName='DateFromFile',HelpMessage="Which of the reference file's attributes to use? (LastAccessTime, LastWriteTime, or CreationTime)")] | |
[ValidateSet("LastAccessTime","LastWriteTime","CreationTime")] | |
[String]$ReferenceProperty, | |
[Switch]$PassThru, | |
[Switch]$Force | |
) | |
begin | |
{ | |
#region 'Domestic Workers' | |
function updateFileSystemInfo | |
{ | |
[cmdletbinding()] | |
Param( | |
[Parameter(Mandatory,Position=0)] | |
[System.IO.FileSystemInfo]$InputObject, | |
[ValidateSet("All","LastAccessTime","LastWriteTime","CreationTime")] | |
[String]$Property = "All", | |
[Parameter(Mandatory,Position=1)] | |
[DateTime]$Date, | |
[Switch]$PassThru | |
) | |
switch ($Property) { | |
'CreationTime' { $InputObject.CreationTime = $FileTime } | |
'LastAccessTime' { $InputObject.LastAccessTime = $FileTime } | |
'LastWriteTime' { $InputObject.LastWriteTime = $FileTime } | |
Default { $InputObject.CreationTime = $FileTime | |
$InputObject.LastAccessTime = $FileTime | |
$InputObject.LastWriteTime = $FileTime } | |
} #endswitch | |
if($PassThru) | |
{ | |
$InputObject | |
} | |
} | |
function touchNewFile | |
{ | |
[cmdletbinding()] | |
Param( | |
[String]$FilePath, | |
[Switch]$Force | |
) | |
$ParentPathExists = (Test-Path -Path (Split-Path $FilePath -Parent)) | |
if($ParentPathExists) | |
{ | |
Set-Content -Path $FilePath -Value $null -Force:$Force | |
} | |
elseif((-Not($ParentPathExists)) -and $Force) | |
{ | |
mkdir (Split-Path $FilePath -Parent) -Force -Confirm:$false | Out-Null | |
Set-Content -Path $FilePath -Value $null -Confirm:$false -Force:$Force | |
} | |
else | |
{ | |
Write-Error "Ensure the path `"$FilePath`" exists or use the -Force Parameter." | |
} | |
} | |
function getFileTime | |
{ | |
Param( | |
[ValidateScript({Test-Path $_ -PathType Leaf})] | |
[String]$FilePath, | |
[ValidateSet("LastAccessTime","LastWriteTime","CreationTime")] | |
[String]$Property = "CreationTime" | |
) | |
switch ($Property) | |
{ | |
'CreationTime' {(Get-ChildItem -Path $FilePath).CreationTime} | |
'LastAccessTime' {(Get-ChildItem -Path $FilePath).LastAccessTime} | |
'LastWriteTime' {(Get-ChildItem -Path $FilePath).LastWriteTime} | |
} | |
} | |
#endregion | |
#region 'Hey, wanna go on a date?' | |
if($Date) | |
{ | |
$FileTime = $Date | |
} | |
elseif($ReferenceFile) | |
{ | |
$FileTime = getFileTime -FilePath $ReferenceFile -Property:$ReferenceProperty | |
} | |
else | |
{ | |
$FileTime = Get-Date | |
} | |
$updateParams = @{Date=$FileTime;Property=$Property;ErrorAction='Stop'} | |
#endregion | |
} | |
process | |
{ | |
foreach($Path in $FilePath) | |
{ | |
#http://stackoverflow.com/questions/3038337/powershell-resolve-path-that-might-not-exist | |
$File = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("$Path") | |
if(Test-Path $File) | |
{ | |
if($PSCmdlet.ShouldProcess($File, "Modify File")) | |
{ | |
updateFileSystemInfo -InputObject (Get-ChildItem $File) @updateParams -PassThru:$PassThru | |
} | |
} | |
else | |
{ | |
if($PSCmdlet.ShouldProcess($File, "Create File")) | |
{ | |
try | |
{ | |
touchNewFile -FilePath $File -Force:$Force -ErrorAction Stop | |
} | |
catch | |
{ | |
Write-Error "Ensure the path `"$FilePath`" exists or use the -Force Parameter." | |
break; | |
} | |
updateFileSystemInfo -InputObject (Get-ChildItem $File) @updateParams -PassThru:$PassThru | |
} | |
} | |
} | |
} | |
} | |
Set-Alias -Name touch -Value Set-File |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment