is there a way to use the equivalent of touch in powershell to update time stamps of a file? is there a way to use the equivalent of touch in powershell to update time stamps of a file? unix unix

is there a way to use the equivalent of touch in powershell to update time stamps of a file?


You can use

$file = Get-Item C:\Intel\Logs\IntelCpHDCPSvc.log$file.LastWriteTime = (Get-Date)

Or CreationTime or LastAcccessTime, if you prefer.

As a function

Function UpdateFileLastWriteTimeToToday() {         Param ($FileName)    $file = Get-Item $FileName    Echo "Current last write time: " $file.LastWriteTime    $file.LastWriteTime = (Get-Date)    Echo "New last write time: " $file.LastWriteTime}#How to useUpdateFileLastWriteTimeToToday -FileName C:\Intel\Logs\IntelGFX.Log

With the output of

Current last write time: Tuesday, April 16, 2019 1:09:49 PMNew last write time: Monday, November 4, 2019 9:59:55 AM


Mark's helpful answer shows how to update a single file's last-modified timestamp.

Below is the source code for function Touch-File, which implements most of the functionality that the Unix touch utility offers in a PowerShell-idiomatic fashion, including support for -WhatIf, verbose output, and a pass-thru option.

It works in both Windows PowerShell (version 3 or higher) and PowerShell Core.

You can put the function in your $PROFILE, for instance; call Get-Help Touch-File for help.
If you want to define an alias, I recommend against naming it touch, to prevent confusion with the native touch utility on Unix-like platforms;
Set-Alias tf Touch-File would work, for instance.

Examples:

# Sets the last-modified and last-accessed timestamps for all text files# in the current directory to the current point in time.Touch-File *.txt# Creates files 'newfile1' and 'newfile2' and outputs information about them as # System.IO.FileInfo instances.# Note the need to use "," to pass multiple paths.Touch-File newfile1, newfile2 -PassThru# Updates the last-modified and last-accessed timestamps for all text files# in the current directory to midnight (the start of) of today's date.Touch-File *.txt -DateTime (Get-Date).Date# Sets the last-modified and last-accessed timestamps of all text files# in the current directory back by 1 hour.Get-Item *.txt | Touch-File -Offset '-1:0'# Sets the last-modified and last-accessed timestamps of all files in the # current directory to the last-modified timestamp of the current directory.Get-ChildItem -File | Touch-File -ReferencePath . '-0:1'

Touch-File source code:

Note:

  • The function below is also available as an MIT-licensed Gist, and only the latter will be maintained going forward. Assuming you have looked at the linked code to ensure that it is safe (which I can personally assure you of, but you should always check), you can install it directly as follows:

    irm https://gist.github.com/mklement0/82ed8e73bb1d17c5ff7b57d958db2872/raw/Touch-File.ps1 | iex
  • Touch is not an approved verb in PowerShell, but it was chosen nonetheless,because none of the approved verbs can adequately convey the core functionality ofthis command.

function Touch-File {  <#  .SYNOPSIS  "Touches" files.  .DESCRIPTION  Similar to the Unix touch utility, this command updates the last-modified and  last-accessed timestamps of files or creates files on  demand.  The current point in time is used by default, but you can pass a  specific timestamp with -DateTime or use an existing file or directory's   last-modified timestamp with -ReferencePath.  Alternatively, the target files' current timestamps can be adjusted with   a time span passed to -Offset.  Symbolic links are invariably followed, which means that it is a file link's  *target* whose last-modified timestamp get updated.  Note:   * This means that a *link*'s timestamp is itself never updated.  * If a link's target doesn't exist, a non-terminating error occurs.  Use -WhatIf to preview the effects of a given command, and -Verbose to see  details.  Use -PassThru to pass the touched items through, i.e., to output updated  information about them.  Note that in order to pass multiple target files / patterns as arguments  you must *comma*-separate them, because they bind to a single, array-valued  parameter.  .PARAMETER Path  The paths of one or more target files, optionally expressed  as wildcard expressions, and optionally passed via the pipeline.  .PARAMETER LiteralPath  The literal paths of one or more target files, optionally  passed via the pipeline as output from Get-ChildItem or Get-Item.  .PARAMETER DateTime  The timestamp to assign as the last-modified (last-write) and last-access  values.  By default, the current point in time is used.  .PARAMETER ReferencePath  The literal path to an existing file or directory whose last-modified  timestamp should be applied to the target file(s).  .PARAMETER Offset  A time span to apply as an offset to the target files' current last-write  timestamp.  Since the intent is to adust the current timestamps of *existing* files,  non-existent paths are ignored; that is, -NoNew is implied.  Note that positive values adjust the timestamps forward (to a more recent date),  whereas negative values adjust backwards (to an earlier date.)  Examples of strings that can be used to specify time spans:  * '-1' adjust the current timestamp backward by 1 day  * '-2:0' sets it backward by 2 hours   Alternatively, use something like -(New-TimeSpan -Days 1)  .PARAMETER NoNew  Specifies that only existing files should have their timestamps updated.  By default, literal target paths that do not refer to existing items   result in files with these paths getting *created* on demand.  A warning is issued for any non-existing input paths.  .PARAMETER PassThru  Specifies that the "touched" items are passed through, i.e. produced as this   command's output, as System.IO.FileInfo instances.  .PARAMETER Force  When wildcard expressions are passed to -Path, hidden files are matched too.  .EXAMPLE  Touch-File *.txt  Sets the last-modified and last-accessed timestamps for all text files  in the current directory to the current point in time.  .EXAMPLE  Touch-File newfile1, newfile2 -PassThru  Creates files 'newfile1' and 'newfile2' and outputs information about them as   System.IO.FileInfo instances.  Note the need to use "," to pass multiple paths.  .EXAMPLE  Touch-File *.txt -DateTime (Get-Date).Date  Updates the last-modified and last-accessed timestamps for all text files  in the current directory to midnight (the start of) of today's date.  .EXAMPLE  Get-Item *.txt | Touch-File -Offset '-1:0'  Adjusts the last-modified and last-accessed timestamps of all text files  in the current directory back by 1 hour.  .EXAMPLE  Get-ChildItem -File | Touch-File -ReferencePath .  Sets the last-modified and last-accessed timestamps of all files in the   current directory to the last-modified timestamp of the current directory.  .NOTES  "Touch" is not an approved verb in PowerShell, but it was chosen nonetheless,  because none of the approved verbs can adequately convey the core functionality  of this command.  In PowerShell *Core*, implementing this command to support multiple target  paths *as individual arguments* (as in Unix touch) would be possible  (via ValueFromRemainingArguments), but such a solution would misbehave in  Windows PowerShell.  #>  # Supports both editions, but requires PSv3+  #requires -version 3    [CmdletBinding(DefaultParameterSetName = 'Path', SupportsShouldProcess)]  param(    [Parameter(ParameterSetName = 'Path', Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]    [Parameter(ParameterSetName = 'PathAndDateTime', Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]    [Parameter(ParameterSetName = 'PathAndRefPath', Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]    [string[]] $Path    ,    [Parameter(ParameterSetName = 'LiteralPath', Mandatory, ValueFromPipelineByPropertyName)]    [Parameter(ParameterSetName = 'LiteralPathAndDateTime', Mandatory, ValueFromPipelineByPropertyName)]    [Parameter(ParameterSetName = 'LiteralPathAndRefPath', Mandatory, ValueFromPipelineByPropertyName)]    [Alias('PSPath', 'LP')]    [string[]] $LiteralPath    ,    [Parameter(ParameterSetName = 'PathAndRefPath', Mandatory)]    [Parameter(ParameterSetName = 'LiteralPathAndRefPath', Mandatory)]    [string] $ReferencePath    ,    [Parameter(ParameterSetName = 'PathAndDateTime', Mandatory)]    [Parameter(ParameterSetName = 'LiteralPathAndDateTime', Mandatory)]    [datetime] $DateTime    ,    [Parameter(ParameterSetName = 'Path')]    [Parameter(ParameterSetName = 'LiteralPath')]    [timespan] $Offset    ,    [switch] $NoNew    ,    [switch] $PassThru    ,    [switch] $Force  )  begin {         Set-StrictMode -Version 1    $ErrorActionPreference = 'Continue' # We want to pass non-terminating errors / .NET method-call exceptions through.    $haveRefPath = $PSBoundParameters.ContainsKey('ReferencePath')    $haveDateTime = $PSBoundParameters.ContainsKey('DateTime')    $haveOffset = $PSBoundParameters.ContainsKey('Offset')    if ($haveOffset) { $NoNew = $true } # -NoNew is implied.    # Initialize defaults (even though they may not be used).    # Defining them unconditionally prevents strict-mode violations in pseudo-ternary conditionals.    if (-not ($haveDateTime -or $haveRefPath)) { $DateTime = [datetime]::Now }    if (-not $haveOffset) { $Offset = 0 }    # If a reference item was given, obtain its timestamp now and abort if that fails.    if ($haveRefPath) {      try {        $DateTime = (Get-Item -ErrorAction Stop $ReferencePath).LastWriteTime      }      catch {        Throw "Failed to get the reference path's last-modified timestamp: $_"      }    }    $touchedCount = 0  }  process {        $wildcardsSupported = $PSCmdlet.ParameterSetName -notlike 'LiteralPath*'    # Try to retrieve existing files.    [array] $files, $dirs =     $(      if ($wildcardsSupported) {        Get-Item -Path $Path -ErrorAction SilentlyContinue -ErrorVariable err -Force:$Force      }      else {        Get-Item -LiteralPath $LiteralPath -ErrorAction SilentlyContinue -ErrorVariable err -Force:$Force      }    ).Where( { -not $_.PSIsContainer }, 'Split')    # Ignore directories among the (globbed) input paths, but issue a warning.    if ($dirs) {      Write-Warning "Ignoring *directory* path(s): $dirs"    }    # -WhatIf / -Confirm support.    # Note: The prompt message is also printed with -Verbose    $targets = ($LiteralPath, ($Path, $files.FullName)[$files.Count -gt 0])[$wildcardsSupported] -replace '^Microsoft\.PowerShell\.Core\\FileSystem::' -replace ('^' + [regex]::Escape($PWD) + '[\\/]?')    if ($targets.Count -gt 1) { $targets = "`n" + ($targets -join "`n") + "`n" }    $newDateTimeDescr = if ($haveOffset -and -not ($haveDateTime -or $haveRefPath)) { "the last-modified timestamp offset by $Offset" } else { "$($DateTime + $Offset)" }    $actionDescr = ("Updating / creating with a last-modified timestamp of $newDateTimeDescr", "Updating the last-modified timestamp to $newDateTimeDescr")[$NoNew.IsPresent]    if (-not $PSCmdlet.ShouldProcess($targets, $actionDescr)) { return }    # Try to create the files that don't yet exist - unless opt-out -NoNew was specified.    if ($err) {      if ($NoNew) {        Write-Warning "Ignoring non-existing path(s): $($err.TargetObject)"      }      else {        $files += foreach ($file in $err.TargetObject) {          Write-Verbose "Creating: $file..."          New-Item -ItemType File -Path $file -ErrorAction SilentlyContinue -ErrorVariable e          # If an error occurred - such as the parent directory of a literal target path not existing - pass it through.          # The only acceptable error is if the file has just been created, between now and the time we ran Get-Item above.          if ($e -and -not (Test-Path -PathType Leaf -LiteralPath $file)) { $e | Write-Error }        }      }    }    # Update the target files' timestamps.    foreach ($file in $files) {      # Note: If $file is a symlink, *setting* timestamp properties invariably sets the *target*'s timestamps.      #       *Getting* a symlink's timestame properties, by contrast, reports the *link*'s.      #       This means:      #          * In order to apply an offset to the existing timestamp, we must explicitly get the *target*'s timestamp      #          * With -PassThru, unfortunately - given that we don't want to quietly switch to the *target* on output -      #            this means that the passed-through instance will reflect the - unmodified - *link*'s properties.      $target =         if ($haveOffset -and $file.LinkType) {          # Note: If a link's target doesn't exist, a non-terminating error occurs, which we'll pass through.          # !! Due to inconsistent behavior of Get-Item as of PowerShell Core 7.2.0-preview.5, if a broken symlink          # !! is (a) specified literally and (b) alongside at least one other path (irrespective of whether -Path or -LiteralPath is used),          # !! it generates an *error* - even though passing that path *as the only one* or *by indirect inclusion via a pattern*          # !! does NOT (it lists the non-existent target in the Name column, but doesn't error).          # !! Thus, if (a) and (b) apply, the resulting error may have caused the non-existent target to be created above,          # !! assuming that its parent directory exists.          Get-Item -Force -LiteralPath $file.Target        } else {           $file         }      if ($target) {        # Set the last-modified and (always also) the last-access timestamps.        $target.LastWriteTime = $target.LastAccessTime = if ($haveOffset) { $target.LastWriteTime + $Offset } else { $DateTime }      }      if ($PassThru) { $file }    }    $touchedCount += $files.Count  }  end {      if (-not $WhatIfPreference -and $touchedCount -eq 0) {      Write-Warning "Nothing to touch."    }  }}