我想从PowerShell检查文件路径是否在给定目录(或其子目录之一)中。
现在我正在做:
$file.StartsWith( $directory, [StringComparison]::InvariantCultureIgnoreCase )
但我确信有更好的方法。
我可以接受$file.Directory
并迭代所有.Parent
,但我希望能有更简单的事情。
编辑:文件可能不存在;我只是在看路径。
答案 0 :(得分:6)
如此简单的事情:
PS> gci . -r foo.txt
这隐式使用-filter参数(按位置)指定foo.txt作为过滤器。您还可以指定* .txt或foo?.txt。 StartsWith的问题在于,当您处理不区分大小写的比较时,仍然存在/和\是PowerShell中的有效路径分隔符的问题。
假设文件可能不存在且$ file和$ directory都是绝对路径,您可以使用“PowerShell”方式执行此操作:
(Split-Path $file -Parent) -replace '/','\' -eq (Get-Item $directory).FullName
但这不是很好,因为你仍然需要规范路径/ - > \但至少PowerShell字符串比较不区分大小写。另一种选择是使用IO.Path规范化路径,例如:
[io.path]::GetDirectoryName($file) -eq [io.path]::GetFullPath($directory)
这个问题的一个问题是,GetFullPath还会根据进程的当前目录创建一个相对路径绝对路径,其次数是不与PowerShell的当前目录相同。所以只要确保$ directory是一个绝对路径,即使你必须像“$ pwd \ $ directory”那样指定它。
答案 1 :(得分:1)
由于路径可能不存在,使用string.StartsWith
可以进行此类测试(尽管OrdinalIgnoreCase
is a better representation of how the file system compares paths)。
唯一需要注意的是路径需要采用规范形式。否则,C:\x\..\a\b.txt
和C:/a/b.txt
之类的路径将失败“这是C:\a\
目录”下的测试。在进行测试之前,您可以使用静态Path.GetFullPath
方法获取路径的全名:
function Test-SubPath( [string]$directory, [string]$subpath ) {
$dPath = [IO.Path]::GetFullPath( $directory )
$sPath = [IO.Path]::GetFullPath( $subpath )
return $sPath.StartsWith( $dPath, [StringComparison]::OrdinalIgnoreCase )
}
另请注意,这不包括逻辑遏制(例如,如果\\some\network\path\
映射到Z:\path\
,则测试\\some\network\path\b.txt
是否在Z:\
下会失败,即使文件可以通过Z:\path\b.txt
)访问。如果您需要支持此行为,these questions可能有所帮助。
答案 2 :(得分:0)
快速的事情:
14:47:28 PS>pwd
C:\Documents and Settings\me\Desktop
14:47:30 PS>$path = pwd
14:48:03 PS>$path
C:\Documents and Settings\me\Desktop
14:48:16 PS>$files = Get-ChildItem $path -recurse |
Where {$_.Name -match "thisfiledoesnt.exist"}
14:50:55 PS>if ($files) {write-host "the file exists in this path somewhere"
} else {write-host "no it doesn't"}
no it doesn't
(在桌面上或桌面上的文件夹中创建新文件,并将其命名为“thisfileexists.txt”)
14:51:03 PS>$files = Get-ChildItem $path -recurse |
Where {$_.Name -match "thisfileexists.txt"}
14:52:07 PS>if($files) {write-host "the file exists in this path somewhere"
} else {write-host "no it doesn't"}
the file exists in this path somewhere
当然迭代仍在发生,但PS正在为你做这件事。如果查找系统/隐藏文件,您也可能需要-force。
答案 3 :(得分:0)
这样的东西?
Get-ChildItem -Recurse $directory | Where-Object { $_.PSIsContainer -and `
$_.FullName -match "^$($file.Parent)" } | Select-Object -First 1
答案 4 :(得分:0)
如果将输入字符串转换为DirectoryInfo和FileInfo,则字符串比较不会有任何问题。
function Test-FileInSubPath([System.IO.DirectoryInfo]$Dir,[System.IO.FileInfo]$File)
{
$File.FullName.StartsWith($Dir.FullName)
}