3

I want to write code that run on all PowerShell platforms. The following code generates output with \ path separators on Windows and / path separators on Linux.

Get-ChildItem -File -Recurse | ForEach-Object { $_.FullName }

I want to exclude files that are anywhere under an obj directory. The number and depth of obj directories is not known. One way to do this would be to filter out those using something like the following. However, this will not work on Linux because the path separator is different.

Get-ChildItem -File -Recurse | 
    Where-Object { -not ($_.FullName -like '*\obj\*' |
    ForEach-Object { $_.FullName }

Using a regex pattern appears to work, but I would like to know if there is a more clear way to do this. I see this as awkward. Not only that, the \\ character is valid as part of a Linux file name which could present a failure vulnerability to this code.

Get-ChildItem -Recurse |
    Where-Object { -not ( $_.FullName -like "*[/\]obj[/\]*") } |
    ForEach-Object { $_.FullName }
lit
  • 14,456
  • 10
  • 65
  • 119
  • 1
    If you knew the level depth of the folder, you could filter on the output of a `Split-Path -leaf` – BenH Jun 15 '17 at 14:59
  • @BenH - That would be one way. Using `-split` and `-in` might work, but that seems like a lot of code for something so simple. I have updated the question to specify that the number and depth of `obj` directories is not known. – lit Jun 15 '17 at 15:14
  • `Where-Object {$_.FullName.split('/\') -notcontains "obj" }` does seems like it would work. – BenH Jun 15 '17 at 15:26
  • This is also a good idea. However, the `\\` character can be a legitimate part of a filename on Linux. Both this, and my suggestion, could fail based on that. I'm still looking for something better. – lit Jun 15 '17 at 15:33

2 Answers2

2

I would suggest to shift responsibility for handling directory separator character to the underlying .Net platform. Something like this:

Get-ChildItem -Recurse |
Where-Object { $_.FullName.Split([IO.Path]::DirectorySeparatorChar) -notcontains "obj" } |
ForEach-Object { $_.FullName }
Mikhail Tumashenko
  • 1,683
  • 2
  • 21
  • 28
  • This works. I am still open to something better/easier. – lit Jun 15 '17 at 17:06
  • So, `[IO.Path]::DirectorySeparatorChar` is like Python's `os.path.sep`. Would that this were automatically created in `Env:pathsep` or `Variable:pathsep` or something like that. – lit Jun 15 '17 at 18:46
  • Don't forget [`[System.IO.Path]::AltDirectorySeparatorChar`](https://msdn.microsoft.com/en-us/library/system.io.path.altdirectoryseparatorchar%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) as well – TessellatingHeckler Jun 15 '17 at 19:23
  • @TessellatingHeckler - Both of these are `/` on Linux. – lit Jun 16 '17 at 12:49
0

From at least PowerShell v6.0.0-beta.2 $PSVersionTable has the additional properties GitCommitId, OS and Platform you could use to distinguish in your code albeit having only one version as in Mikhails answer is preferable.

$PSVersionTable                                                                                                                  

Name                           Value                                                                                               
----                           -----                                                                                               
PSVersion                      6.0.0-beta                                                                                          
PSEdition                      Core                                                                                                
BuildVersion                   3.0.0.0                                                                                             
CLRVersion                                                                                                                         
GitCommitId                    v6.0.0-beta.2                                                                                       
OS                             Linux 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017                                  
Platform                       Unix                                                                                                
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                             
PSRemotingProtocolVersion      2.3                                                                                                 
SerializationVersion           1.1.0.1                                                                                             
WSManStackVersion              3.0