7

我想从 PowerShell 检查文件路径是否在给定目录(或其子目录之一)中。

现在我正在做:

$file.StartsWith(  $directory, [StringComparison]::InvariantCultureIgnoreCase )

但我相信有更好的方法。

我可以接受$file.Directory并遍历所有.Parents,但我希望有更简单的东西。

编辑:文件可能不存在;我只是在看路。

4

5 回答 5

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”一样指定它。

于 2009-06-23T00:44:48.193 回答
2

由于路径可能不存在,因此 usingstring.StartsWith可以很好地进行此类测试(尽管OrdinalIgnoreCase它可以更好地表示文件系统如何比较路径)。

唯一需要注意的是路径需要采用规范形式。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

于 2009-11-14T14:04:25.137 回答
0

Something real quick:

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

(create new file on desktop or in a folder on the desktop and name it "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

Of course iterating is still happening, but PS is doing it for you. You also might need -force if looking for system/hidden files.

于 2009-06-22T22:02:22.293 回答
0

像这样的东西?

Get-ChildItem -Recurse $directory | Where-Object { $_.PSIsContainer -and `
    $_.FullName -match "^$($file.Parent)" } | Select-Object -First 1
于 2009-06-23T18:12:07.037 回答
0

如果将输入字符串转换为 DirectoryInfo 和 FileInfo,则字符串比较不会有任何问题。

function Test-FileInSubPath([System.IO.DirectoryInfo]$Dir,[System.IO.FileInfo]$File)
{
    $File.FullName.StartsWith($Dir.FullName)
}
于 2014-03-31T14:50:10.097 回答