1

I am trying to generate an html page with file index. This approach worked seamlessly:

$htmlout = Get-ChildItem -Path "$SearchPath" -Filter "$fileType" -Recurse |
Select @{Name="Link";Expression={("<a rel=" + $_.FullName + " href=file:///" + $_.FullName + ">$_</a>")}}

The Link column had file names only (i.e. test.txt) and displayed file content when clicking on it. Then we've got an additional requirement to skip old files. The script is now:

$htmlout = Get-ChildItem -Path "$SearchPath" -Recurse -include ("$fileType") | Where-Object {$_.LastWriteTime -ge "01/01/2014"} |` Select @{Name="Link";Expression={("<a rel=" + $_.FullName + " href=file:///" + $_.FullName + ">$_</a>")}}

It still works, but Link column now displays the entire file path + file name (i.e. \fileserver\folder1\folder2\test.txt). Adding >$_.Name< does not work here.

I am trying to understand why the same URL line behaves differently after filter change.

Nik
  • 161
  • 1
  • 13
  • I can't see that it behaves differently; your first version includes the full path to the filename when I try it. And your `Adding >$_.Name< does not work here.` is because you can't access a property in a string like that: see: http://stackoverflow.com/questions/1145704/how-can-you-use-an-objects-property-in-a-string – TessellatingHeckler Oct 05 '16 at 01:32
  • It's not completely necessary, but I suggest that you do not arbitrarily wrap your variables in quotes if they are already strings, or wrapping them in parentheses when they are already self-contained. – Jessie Westlake Oct 05 '16 at 09:21

1 Answers1

1

Background

As far as I can tell, there is a discrepancy with the interaction between the .ToString() method and the DefaultDisplayProperty of objects returned by Get-ChildItem.

The behavior manifests when both of the following conditions are true:
- The -filter parameter is being used.
- The value of the -Path parameter resolves to a single directory, whether or not -Recurse is used.

Under the above circumstances, the .ToString() method implemented by PowerShell uses the Name property as default, rather than FullName as is the case in all other scenarios.

My guess is that this inconsistency is due to the underlying object types returned by the FileSystem provider when -Filter is used, rather than the objects PowerShell returns when it handles the search/filter itself (as is the case with -Include).

Observation

When you wrap your $_ pipeline object variable in double quotes, PowerShell's type-conversion implicitly calls the .ToString() method and you get the resulting name variation.

Solution

To correct your issue, you could simply use -Filter in both code examples and get the desired output, however, that is prone to cause problems sooner or later.

The more appropriate way to negate the problem is to properly use a PowerShell sub-expression within the double-quoted strings.

To create a sub-expression, simply wrap the desired code like so: $(). This creates a separation between which characters are code and which are part of the string; in your case allowing you to use the member access operator .. The method also alleviates the need to do string concatenation with the + operator.

Solution Code:

$HTMLOut = Get-ChildItem -Path $SearchPath -Recurse -Include $FileType | Where-Object {$_.LastWriteTime -ge "01/01/2014"} | Select @{Name="Link";Expression={("<a rel=$($_.FullName) href=file:///$($_.FullName)>$($_.Name)</a>")}}
Jessie Westlake
  • 159
  • 2
  • 11
  • As a side-note, you should probably wrap your FullName in literal double-quotes in case the file paths have spaces, or else your HTML will likely break. To escape the second set of double-quotes, use the backtick `. – Jessie Westlake Oct 05 '16 at 09:24
  • Thank you @Jessie for the elaborated answer, it does work as expected now! – Nik Oct 05 '16 at 15:53