这里的问题是从 Powershell 开始(或至少从 PS2.0 开始)引入的故意“错误”(我称之为)。为了简化从 cmd 到 Powershell 的转换,Get-ChildItem 被赋予别名 dir,然后使其像 dir 的 cmd 版本一样工作(尽可能提供类似外观的输出)。和cmd一样,
PS > dir <directory path>
产生 的列表(当简单显示时)。在这两种情况下(cmd 和 Powershell),缺少的目录路径使用 . (当前目录)。但是,如果 cmd 版本在目录路径之后使用文件名或通配符模式调用(同样,如果没有目录路径,则为隐含的 .),则输出是匹配的文件(以及通配符大小写的目录)该目录(如果有)。 Get-ChildItem 执行相同的操作,因此别名 dir 提供类似的输出。可能已经预料到Get-ChildItem 在提供通配符路径时会返回与该通配符路径匹配的任何目录的children 列表并忽略任何匹配的文件。如果参数是纯文件名,Get-ChildItem 会抱怨提供的参数不能有子级(与 可以 有子级但没有子级的空目录相反)。毕竟,如果你想匹配文件或目录本身(而不是它们的内容),你会使用Get-Item。实际上,Get-ChildItem 在文件参数和通配符的情况下返回的结果与等效的Get-Item 相同。但是,Get-ChildItem 为指定目录路径的实际子级返回的结果与Get-Item 的结果略有不同。具体来说,它们有不同的 ToString() 方法(即使它们都返回 FileInfo 或 DirectoryInfo 对象)。这意味着通过显式调用ToString() 或在需要字符串的表达式中使用返回的对象,例如
将对象转换为字符串
PS > dir | foreach { "$_" }
给出不同的结果。
示范,
PS > gci C:\Windows\Web\Screen | foreach { "$_" }
img100.jpg
img101.png
img102.jpg
img103.png
img104.jpg
img105.jpg
PS > gci C:\Windows\web\screen\* | foreach { "$_" }
C:\Windows\web\screen\img100.jpg # note: uses argument path case.
C:\Windows\web\screen\img101.png # actual directory path case is
C:\Windows\web\screen\img102.jpg # C:\WINDOWS\Web\Screen
C:\Windows\web\screen\img103.png
C:\Windows\web\screen\img104.jpg
C:\Windows\web\screen\img105.jpg
PS > gi C:\Windows\Web\screen\* | foreach { "$_" }
C:\Windows\Web\screen\img100.jpg
C:\Windows\Web\screen\img101.png
C:\Windows\Web\screen\img102.jpg
C:\Windows\Web\screen\img103.png
C:\Windows\Web\screen\img104.jpg
C:\Windows\Web\screen\img105.jpg
PS > gci C:\Windows\Web\screen\img100.jpg | foreach { "$_" }
C:\Windows\Web\screen\img100.jpg
PS > gi C:\Windows\Web\screen\img100.jpg | foreach { "$_" }
C:\Windows\Web\screen\img100.jpg
因此,我怀疑 OP 正在使用隐式字符串转换来获取文件的“名称”并运行此“错误”的犯规,这显然在使用 -Exclude 时也会表现出来(独立于 -Recurse 有没有效果)。解决方案是不依赖字符串转换并使用实际的字符串属性,名称或全名(无论需要哪个)。
PS > gci C:\Windows\Web\Screen | foreach { "$($_.fullname)" }
C:\Windows\Web\screen\img100.jpg
C:\Windows\Web\screen\img101.png
C:\Windows\Web\screen\img102.jpg
C:\Windows\Web\screen\img103.png
C:\Windows\Web\screen\img104.jpg
C:\Windows\Web\screen\img105.jpg
PS > gci C:\Windows\web\screen\* | foreach { "$($_.name)" }
img100.jpg
img101.png
img102.jpg
img103.png
img104.jpg
img105.jpg
另一种(长期)解决方案可能是修复Get-ChildItem,以便ToString() 始终返回相同的结果。这可能被认为是一个重大变化,但我怀疑这个“错误”已经让许多用户感到困惑,甚至那些已经意识到它的用户。我知道我一直在忘记。甚至可以让Get-Item 和Get-ChildItem 使用相同的ToString(),无论是哪个。
对于激进的(并且可能引发地狱)解决方案,“修复”Get-ChildItem 以仅返回子项(或错误)并使dir 成为根据需要调用Get-ChildItem 或Get-Item 的函数。然后,这将恢复 Powershell 的“cmdlet 做他们名字所说的事情”的精神,而不是让Get-ChildItem 有时返回子项,有时返回项。 (改变太多了,所以不要屏住呼吸。)
使用 PS 5.1.18362.145 进行测试。