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

7
我希望检查一个文件路径是否在给定目录(或其子目录之一)中,从PowerShell进行操作。
现在我正在执行以下操作:
$file.StartsWith(  $directory, [StringComparison]::InvariantCultureIgnoreCase )

但我相信有更好的方法。

我可以使用$file.Directory并遍历所有的.Parent,但我希望有更简单的方法。

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

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"这样指定它。


+1. 能够分别指定-path和-fil非常方便。学会它,爱上它。 - Richard Berg

2
由于路径可能不存在,因此使用 string.StartsWith 来进行这种类型的测试是可以的(尽管OrdinalIgnoreCase 是文件系统比较路径的更好表示)。
唯一的注意事项是路径需要处于规范形式。否则,像 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访问)。如果你需要支持此行为,请参考这些问题

1
如果您将输入字符串转换为DirectoryInfo和FileInfo,那么在字符串比较方面就不会有任何问题。
function Test-FileInSubPath([System.IO.DirectoryInfo]$Dir,[System.IO.FileInfo]$File)
{
    $File.FullName.StartsWith($Dir.FullName)
}

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参数。


1
我对文件是否存在并不感兴趣,但我关心它的路径是否在某个目录下。此外,你的格式不清楚。 - Jay Bazuzi
是的,这里的代码格式对于PS来说不太好用。这不是一个完整的PS1文件,只是在PS命令行上输入的一些内容。你的问题是“如何检查文件是否在给定目录下...”,看起来其他答案也在检查文件,就像你所问的那样。我看到了你的编辑,但如果文件甚至不存在,它怎么可能有路径呢? - Bratch
我现在明白了,你有一个文件路径存储在某个地方,想要查看该路径是否存在于其他指定路径下面? - Bratch

0

像这样吗?

Get-ChildItem -Recurse $directory | Where-Object { $_.PSIsContainer -and `
    $_.FullName -match "^$($file.Parent)" } | Select-Object -First 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接