I've noticed that when Get-Content path/to/logfile -Wait
, the output is actually not refreshed every second as the documentation explains it should. If I go in Windows Explorer to the folder where the log file is and Refresh the folder, then Get-Content
would output the latest changes to the log file.
If I try tail -f
with cygwin on the same log file (not at the same time than when trying get-content
), then it tails as one would expect, refreshing real time without me having to do anything.
Does anyone have an idea why this happens?
Description. The Get-Help cmdlet displays information about PowerShell concepts and commands, including cmdlets, functions, Common Information Model (CIM) commands, workflows, providers, aliases, and scripts. To get help for a PowerShell cmdlet, type Get-Help followed by the cmdlet name, such as: Get-Help Get-Process .
Description. The Get-ChildItem cmdlet gets the items in one or more specified locations. If the item is a container, it gets the items inside the container, known as child items. You can use the Recurse parameter to get items in all child containers and use the Depth parameter to limit the number of levels to recurse.
The Get-Item cmdlet gets the item at the specified location. It doesn't get the contents of the item at the location unless you use a wildcard character ( * ) to request all the contents of the item. This cmdlet is used by PowerShell providers to navigate through different types of data stores.
Static member operator :: To find the static properties and methods of an object, use the Static parameter of the Get-Member cmdlet. The member name may be an expression. PowerShell Copy.
Edit: Bernhard König reports in the comments that this has finally been fixed in Powershell 5.
You are quite right. The -Wait
option on Get-Content
waits until the file has been closed before it reads more content. It is possible to demonstrate this in Powershell, but can be tricky to get right as loops such as:
while (1){ get-date | add-content c:\tesetfiles\test1.txt Start-Sleep -Milliseconds 500 }
will open and close the output file every time round the loop.
To demonstrate the issue open two Powershell windows (or two tabs in the ISE). In one enter this command:
PS C:\> 1..30 | % { "${_}: Write $(Get-Date -Format "hh:mm:ss")"; start-sleep 1 } >C:\temp\t.txt
That will run for 30 seconds writing 1 line into the file each second, but it doesn't close and open the file each time.
In the other window use Get-Content
to read the file:
get-content c:\temp\t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" }
With the -Wait
option you need to use Ctrl+C to stop the command so running that command 3 times waiting a few seconds after each of the first two and a longer wait after the third gave me this output:
PS C:\> get-content c:\temp\t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 8: Write 12:15:09 read at 12:15:09 PS C:\> get-content c:\temp\t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 13: Write 12:15:14 read at 12:15:15 PS C:\> get-content c:\temp\t.txt -tail 1 -wait | % { "$_ read at $(Get-Date -Format "hh:mm:ss")" } 19: Write 12:15:20 read at 12:15:20 20: Write 12:15:21 read at 12:15:32 21: Write 12:15:22 read at 12:15:32 22: Write 12:15:23 read at 12:15:32 23: Write 12:15:24 read at 12:15:32 24: Write 12:15:25 read at 12:15:32 25: Write 12:15:26 read at 12:15:32 26: Write 12:15:27 read at 12:15:32 27: Write 12:15:28 read at 12:15:32 28: Write 12:15:29 read at 12:15:32 29: Write 12:15:30 read at 12:15:32 30: Write 12:15:31 read at 12:15:32
From this I can clearly see:
Also when I repeated the exercise with the Get-Content
command running in two other windows one window read line 3 then just waited, the other window read line 6, so the line is definitely being written to the file.
It seems pretty conclusive that the -Wait
option is waiting for a file close event, not waiting for the advertised 1 second. The documentation is wrong.
Edit: I should add, as Adi Inbar seems to insistent that I'm wrong, that the examples I gave here use Powershell only as that seemed most appropriate for a Powershell discussion. I did also verify using Python that the behaviour is exactly as I described:
Content written to a file is readable by a new Get-Content -Wait
command immediately provided the application has flushed its buffer.
A Powershell instance using Get-Content -Wait
will not display new content in the file that is being written even though another Powershell instance, started later, sees the later data. This proves conclusively that the data is accessible to Powershell and Get-Content -Wait
is not polling at 1 second intervals but waiting for some trigger event before it next looks for data.
The size of the file as reported by dir
is updating while lines are being added, so it is not a case of Powershell waiting for the directory entry size to be updated.
When the process writing the file closes it, the Get-Content -Wait
displays the new content almost instantly. If it were waiting until the data was flushed to disk there would be up to a delay until Windows flushed it's disk cache.
@AdiInbar, I'm afraid you don't understand what Excel does when you save a file. Have a closer look. If you are editing test.xlsx
then there is also a hidden file ~test.xlsx
in the same folder. Use dir ~test.xlsx -hidden | select CreationTime
to see when it was created. Save your file and now test.xlsx
will have the creation time from ~test.xlsx
. In other words saving in Excel saves to the ~
file then deletes the original, renames the ~
file to the original name and creates a new ~
file. There's a lot of opening and closing going on there.
Before you save it has the file you are looking at open, and after that file is open, but its a different file. I think Excel is too complex a scenario to say exactly what triggers Get-Content
to show new content but I'm sure you mis-interpreted it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With