1
votes

I recently added a touch function in PowerShell profile file

PS> notepad $profile
function touch {Set-Content -Path ($args[0]) -Value ($null)}

Saved it and ran a test for

touch myfile.txt

error returned:

touch : The term 'touch' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:1
+ touch myfile
+ ~~~~~
    + CategoryInfo          : ObjectNotFound: (touch:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
3
Did you close and reopen the powershell console? - user6811411
Yes I did it multiple times, still did not work. - Muhammad Yasir Javed
That is not a proper implementation of touch, unless you like the idea of accidentally destroying files. If this "function" of touch is all you need, consider renaming it Empty-File or similar... Or consider a more careful implementation, like Add-Content $File $null ; (dir $File).LastWriteTime = Get-Date. - Jeroen Mostert
Have you double checked the path of the profile file and that it actually gets loaded? Type explorer $profile in the console to verify the path and maybe add write-host loaded to the profile to verify it gets loaded. - marsze

3 Answers

4
votes

With PowerShell there are naming conventions for functions. It is higly recommended to stick with that if only to stop getting warnings about it if you put those functions in a module and import that.

A good read about naming converntion can be found here.

Having said that, Powershell DOES offer you the feature of Aliasing and that is what you can see here in the function below.

As Jeroen Mostert and the others have already explained, a Touch function is NOT about destroying the content, but only to set the LastWriteTine property to the current date. This function alows you to specify a date yourself in parameter NewDate, but if you leave it out it will default to the current date and time.

function Set-FileDate {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, Mandatory = $true, Position = 0)]
        [string[]]$Path,
        [Parameter(Mandatory = $false, Position = 1)]
        [datetime]$NewDate = (Get-Date),
        [switch]$Force
    )
    Get-Item $Path -Force:$Force | ForEach-Object { $_.LastWriteTime = $NewDate }
}
Set-Alias Touch Set-FileDate -Description "Updates the LastWriteTime for the file(s)"

Now, the function has a name PowerShell won't object to, but by using the Set-Alias you can reference it in your code by calling it touch

3
votes

Here is a version that creates a new file if it does not exist or updates the timestamp if it does exist.

Function Touch-File
{
    $file = $args[0]
    if($file -eq $null) {
        throw "No filename supplied"
    }

    if(Test-Path $file)
    {
        (Get-ChildItem $file).LastWriteTime = Get-Date
    }
    else
    {
        echo $null > $file
    }
}

If you have a set of your own custom functions stored in a .ps1 file, you must first import them before you can use them, e.g.

Import-module .\MyFunctions.ps1 -Force
0
votes

To avoid confusion:

  • If you have placed your function definition in your $PROFILE file, it will be available in future PowerShell sessions - unless you run . $PROFILE in the current session to reload the updated profile.

    • Also note that loading of $PROFILE (all profiles) can be suppressed by starting a session with powershell.exe -NoProfile (Windows PowerShell) / pwsh -NoProfile (PowerShell (Core)).
  • As Jeroen Mostert points out in a comment on the question, naming your function touch is problematic, because your function unconditionally truncates an existing target file (discards its content), whereas the standard touch utility on Unix-like platforms leaves the content of existing files alone and only updates their last-write (and last-access) timestamps.

  • See this answer for more information about the touch utility and how to implement equivalent behavior in PowerShell.