I've found a weird behavior using powershell.
The output of a quoted object alone differs from the output of the ToString() method invoked on the same object.
what is the method or property invoked in
Write-Output "$a"
This is the directory I'm running the example
> PS C:\temp\testps> DIR
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
-a--- 03/12/2010 11.21 8 2.txt
-a--- 03/12/2010 11.21 8 3.txt
Here I assign the file collection to the $q object
PS C:\temp\testps> $q = Get-ChildItem . "*.txt"
Now I want to print the file names , but I receive an unexpected output
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a}
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
-a--- 03/12/2010 11.21 8 2.txt
-a--- 03/12/2010 11.21 8 3.txt
Putting quotes around the object name shows the right behavior
PS C:\temp\testps> foreach ($a in $q) {Write-Output "$a"}
1.txt
2.txt
3.txt
This is the output for just the first object. It looks like the whole DIR command output till the first filename. Unparsed.
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a;break}
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
The ToString() method behaves like the quoted object.
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a.ToString()}
1.txt
2.txt
3.txt
In the first case Write-Output $a
, the object (System.IO.FileInfo) is formatted by the PowerShell formatting engine based on the format data stored in $pshome\FileSystem.format.ps1xml
. That is, what is really executing is:
Write-Output $a | Out-Default
Out-Default is implicitly executed at the end of the pipeline and it is the cmdlet that does the formatting based on the formatting data.
In the "$a"
case, the ToString()
representation is used.
Write-Output is really just an explicit way to send the object you give it to the next command in the pipleine. Since you don't capture the output, PowerShell uses the default formatting for the object. This is because Write-Output is not actually sending a string to stdout, it is returning an object to the pipeline. The object in the first case is an array of FileSystemInfo objects.
When you return an array in PowerShell without capturing the output, PowerShell attempts to iterate over the array and use its default formatting spec to display each object as text on stdout.
So, in order of the examples your provided, starting with dir
:
dir
returns System.Array[System.IO.FileSystemInfo]. Since the array is not captured by any code, PowerShell uses its default format for FileSystemInfo to display the contents of the array.
the same thing happens as above, but it's you that performs the iteration. You're actually writing your own array back to the pipeline, reconstructing the same object that was returned by get-childitem
in the first place. Since, once again, no code is capturing the output array object, PowerShell displays it just like in the first case. It's as if you wrote:
PS C:\temp\testps> $q = Get-ChildItem . "*.txt"
PS C:\temp\testps> $children = foreach ($a in $q) {Write-Output $a}
PS C:\temp\testps> $children
Hopefully this makes it clear that your example is functionally equivalent to your first example.
Here, you're converting each object in the array to a string by placing it in quotes (which tells PowerShell to call $a.tostring()
) before returning the result array. So this time, you're returning an array of strings to the pipeline. Since you don't capture that array, PowerShell does its default text output to the console, which in the case of a string, is just the text of the string.
This is similar to cases 1 and 2 in that PowerShell is using its default output format for a FileSystemInfo object.
This does the same as 3 because you're returning an array of strings again. The only difference is semantic... you're calling ToString()
explicitly rather than implicitly like when you place the object in quotes.
For more information on default formatting, check out help about_format
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