如何在PowerShell中检查文件是否在给定目录下?

时间:2009-06-22 21:28:12

标签: file powershell directory contains

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

现在我正在做:

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

但我确信有更好的方法。

我可以接受$file.Directory并迭代所有.Parent,但我希望能有更简单的事情。

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

5 个答案:

答案 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.txtC:/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)
}