I want to check if a file path is in a given directory (or one of its subdirectories), from PowerShell.
Right now I'm doing:
$file.StartsWith( $directory, [StringComparison]::InvariantCultureIgnoreCase )
but I'm sure there are better ways.
I could do take $file.Directory
and iterate over all .Parent
s, but I was hoping for something simpler.
EDIT: the file may not exist; I'm just looking at the path.
Test-Path cmdlet is used to check existence of a file.
To search the content in the file in PowerShell, you need to first get the content from the file using Get-Content command and then you need to add Select-String pipeline command. In the below example, we need to search the lines which contain the Get word. You can use multiple patterns to search for the result.
If you want to list files and directories of a specific directory, utilize the “-Path” parameter in the “Get-ChildItem” command. This option will help PowerShell list all the child items of the specified directory. The “-Path” parameter is also utilized to set the paths of one or more locations of files.
Using Test-Path. The first way is the Test-Path cmdlet, specifically designed to determine whether a path or file exists. When using this cmdlet to test whether a file exists, the result is true or false. The result indicates whether the file exists or not.
How about something as simple as:
PS> gci . -r foo.txt
This implicitly uses the -filter parameter (by position) specifying foo.txt as the filter. You could also specify *.txt or foo?.txt. The problem with StartsWith is that while you handle the case-insensitive compare there is still the issue that both / and \ are valid path separators in PowerShell.
Assuming the file may not exist and both $file and $directory are absolute paths, you can do this the "PowerShell" way:
(Split-Path $file -Parent) -replace '/','\' -eq (Get-Item $directory).FullName
But that isn't great since you still have to canonical the path / -> \ but at least the PowerShell string compare is case-insensitive. Another option is to use IO.Path to canonicalize the path e.g.:
[io.path]::GetDirectoryName($file) -eq [io.path]::GetFullPath($directory)
One issue with this is that GetFullPath will also make a relative path an absolute path based on the process's current dir which more times than not, is not the same as PowerShell's current dir. So just make sure $directory is an absolute path even if you have to specify it like "$pwd\$directory".
Since the path might not exist, using string.StartsWith
is fine for doing this type of test (though OrdinalIgnoreCase
is a better representation of how the file system compares paths).
The only caveat is that the paths need to be in a canonical form. Otherwise, paths like C:\x\..\a\b.txt
and C:/a/b.txt
would fail the "is this under the C:\a\
directory" test. You can use the static Path.GetFullPath
method to get the full names of the paths before you do the test:
function Test-SubPath( [string]$directory, [string]$subpath ) {
$dPath = [IO.Path]::GetFullPath( $directory )
$sPath = [IO.Path]::GetFullPath( $subpath )
return $sPath.StartsWith( $dPath, [StringComparison]::OrdinalIgnoreCase )
}
Also note that this does not cover logical containment (e.g. if you have \\some\network\path\
mapped to Z:\path\
, testing whether \\some\network\path\b.txt
is under Z:\
will fail, even though the file can be accessed through Z:\path\b.txt
). If you need to support this behavior, these questions might help.
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