Search code examples
powershellfiletimestamppipesystem-administration

How to create an empty log or text file with Powershell using date or timestamp?


How to create an empty file with powershell, similar to "touch" on Linux, with a timestamp in the filename?

not too different from:

md5sum /etc/mtab > "$(date +"%Y_%m_%d_%I_%M_%p").log"

although that file isn't actually empty, but it does have the date incorporated into the filename itself.

Attempts on Powershell:

PS /home/nicholas/powershell/file_ops> New-Item -ItemType file  foo.txt

New-Item: The file '/home/nicholas/powershell/file_ops/foo.txt' already exists.

New-Item: The file '/home/nicholas/powershell/file_ops/foo.txt' already exists.
PS /home/nicholas/powershell/file_ops> New-Item -ItemType file  bar.txt

    Directory: /home/nicholas/powershell/file_ops

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-----          12/20/2020 10:56 AM              0 bar.txt

PS /home/nicholas/powershell/file_ops> $logfile = "./"+$FN+"-LOG-AddUser_$(get-date -Format yyyymmdd_hhmmtt).txt"

ideally, to generate an arbitrary number of empty log or text files.

see also:

https://community.spiceworks.com/topic/1194231-powershell-adding-a-variable-into-a-log-filename

https://superuser.com/q/502374/977796

https://4sysops.com/archives/understanding-the-powershell-_-and-psitem-pipeline-variables/

https://unix.stackexchange.com/q/278939/101935


Solution

  • In the simplest case, if you want to unconditionally create a file, use New-Item -Force - but note that if the target file exists, its content is discarded:

    # CAVEAT: Truncates an existing file. `-ItemType File` is implied.
    #  * Outputs a [System.IO.FileInfo] instance describing the new file, which
    # $null = ... discards here.
    #  * `Get-Date -UFormat` allows you to perform Unix-style date formatting.
    $null = New-Item -Force "$(Get-Date -UFormat "%Y_%m_%d_%I_%M_%p").log"
    
    • New-Item's (positionally implied) -Path parameter supports an array of paths, so you can pass multiple paths at once.

    • By default, an empty file is created, but you may optionally provide (initial) content via the -Value parameter.


    More work is needed if you truly want to emulate the touch Unix utility's behavior, which by default means (note that touch supports a variety of options[1]):

    • If a file doesn't exist yet, create it (as an empty file).
    • Otherwise, update the last-modified timestamp to the current point in time (and leave the existing content alone).
    $file = "$(Get-Date -UFormat "%Y_%m_%d_%I_%M_%p").log"
    # Trick: This dummy operation leaves an existing file alone,
    #        but creates the file if it doesn't exist.
    Add-Content -LiteralPath $file -Value $null
    (Get-Item -LiteralPath $file).LastWriteTime = Get-Date
    

    Note:

    • The above is limited to a single file specified by literal path, and doesn't include error handling.

    • See this answer for custom PowerShell function Touch-File, which implements most of the touch utility's functionality in PowerShell-idiomatic fashion, including the ability to handle wildcard patterns correctly.

      • Said function is also available as an MIT-licensed Gist. 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
        

    [1] The linked page is touch's POSIX spec, which mandates minimum functionality; concrete implementations may support more.