Get-ChildItem-排除返回全名而不是短名称



运行Get-ChildItem-Exclude时遇到一个奇怪的问题。

在运行了一个副本并比较了这两个目录之后,我一直在源位置和目标位置使用以下命令来创建一个文件阵列。它一直运行得很好。(我本来打算发布图片,但没有足够高的声誉)

$sourcefiles = @(Get-ChildItem -Recurse -path e:Homeo365.test)

当我运行此命令时,数组将填充文件的短名称。

我从文件副本中排除了PST文件,我还需要在比较中排除它们,所以我在GCI命令中添加了一个排除。

$sourcefiles = @(Get-ChildItem -Recurse -path e:Homeo365.test -Exclude *.pst)

这会返回所有正确的文件(*.pst实际上被排除在外),但它返回的是文件的全名,而不是我以前总是返回的短名称。

这导致比较对象失败,因为目标GCI没有排除(由于*.pst已从副本中排除,因此不需要)。此外,它是一个UNC路径,而且全名无论如何都不匹配。

我意识到我可以使用分路径叶子(我已经尝试过了,而且似乎有效)

$sourcefiles = @(Get-ChildItem -Recurse -path e:Homeo365.test -Exclude *.pst | Split-Path -Leaf) 

但我仍然不明白为什么在GCI中添加-exclude参数会导致它更改返回的格式。

有人知道为什么会发生这种情况吗?

提前感谢您的帮助!

好吧,我无法复制您在这里看到的内容。在PowerShell中,将at符号放在操作之前实际上就是数组运算符,简单地说,将其放在带有操作的括号之前不会像您描述的那样返回单个属性。

现在,如果在括号后面放置一个属性名称,只选择一个属性,就可以实现这一点。例如:

$files = @(Get-ChildItem -path c:temp).BaseName
>LZelda.csv
>msvcr100.dll
>names-0.txt
>names-1.txt
>NOBGW00017.log
>nslookup.exe
>PolicySpy.exe

添加-Exclude括号根本不会更改输出。

$files = @(Get-ChildItem -path c:temp -exclude *.png)
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        3/18/2015   2:34 PM                Android
da----        9/10/2013   7:17 PM                Bootfiles
d-----       12/13/2014   4:29 PM                camera
d-----         1/6/2015  11:49 AM                CFS
d-----       12/11/2014   1:08 PM                ebay
d-----         2/2/2014   1:55 PM                Finance

我向您展示这一点的原因是,我们得到的东西仍然是FileSystem对象。将$files减少为只包含一个属性的唯一方法,如FullName、BaseName或以下两种方法中的任何属性:

$files = @(Get-ChildItem -path c:temp -exclude *.png).BaseName
$files = @(Get-ChildItem -path c:temp -exclude *.png | Select -Expand BaseName)

两者将给出相同的输出。

这里的问题是故意的"bug";(我称之为)从Powershell开始就引入了(或者至少从PS2.0开始)。为了简化从cmd到Powershell的转换,Get-ChildItem被赋予了别名dir,然后像dircmd版本一样工作(只要有必要,就可以提供类似的输出)。与cmd一样,

PS > dir <directory path>

产生<目录路径>(当简单显示时)。在这两种情况下(cmd和Powershell),都会使用不存在的目录路径。(当前目录)。但是,如果cmd版本是在目录路径之后使用文件名或通配符模式调用的(同样是隐式的。如果没有目录路径),则输出是该目录中的匹配文件(以及通配符情况下的目录)(如果有)。Get-ChildItem也这样做,所以别名dir给出类似的输出。当提供通配符路径时,Get-ChildItem可能会返回与该通配符路径匹配的任何目录的子目录的列表,并忽略任何匹配的文件。如果参数是纯文件名,Get-ChildItem会抱怨提供的参数不能有子目录(而不是空目录,可以有子目录,但没有)。毕竟,如果您想匹配文件或目录本身(而不是它们的内容),您应该使用Get-Item。事实上,在文件参数和通配符的情况下,Get-ChildItem返回的结果与等效的Get-Item相同。然而,Get-ChildItem为指定目录路径的实际子级返回的结果与Get-Item的结果略有不同。具体来说,它们有不同的ToString()方法(即使它们都返回FileInfo或DirectoryInfo对象)。这意味着通过显式调用ToString()或在需要字符串的表达式中使用返回的对象(例如)将对象转换为字符串

PS > dir | foreach { "$_" }

给出了不同的结果。演示,

PS > gci C:WindowsWebScreen | foreach { "$_" }
img100.jpg
img101.png
img102.jpg
img103.png
img104.jpg
img105.jpg
PS > gci C:Windowswebscreen* | foreach { "$_" }
C:Windowswebscreenimg100.jpg # note: uses argument path case.
C:Windowswebscreenimg101.png # actual directory path case is
C:Windowswebscreenimg102.jpg # C:WINDOWSWebScreen
C:Windowswebscreenimg103.png
C:Windowswebscreenimg104.jpg
C:Windowswebscreenimg105.jpg
PS > gi C:WindowsWebscreen* | foreach { "$_" }
C:WindowsWebscreenimg100.jpg
C:WindowsWebscreenimg101.png
C:WindowsWebscreenimg102.jpg
C:WindowsWebscreenimg103.png
C:WindowsWebscreenimg104.jpg
C:WindowsWebscreenimg105.jpg
PS > gci C:WindowsWebscreenimg100.jpg | foreach { "$_" }
C:WindowsWebscreenimg100.jpg
PS > gi C:WindowsWebscreenimg100.jpg | foreach { "$_" }
C:WindowsWebscreenimg100.jpg

因此,我怀疑OP正在使用隐式字符串转换来获得";name";文件和运行犯规";bug";当使用CCD_ 20时(独立于没有效果的CCD_。解决方案是不依赖于字符串转换,而是使用实际的字符串属性,无论是名称还是全名(以需要的为准)。

PS > gci C:WindowsWebScreen | foreach { "$($_.fullname)" }
C:WindowsWebscreenimg100.jpg
C:WindowsWebscreenimg101.png
C:WindowsWebscreenimg102.jpg
C:WindowsWebscreenimg103.png
C:WindowsWebscreenimg104.jpg
C:WindowsWebscreenimg105.jpg
PS > gci C:Windowswebscreen* | foreach { "$($_.name)" }
img100.jpg
img101.png
img102.jpg
img103.png
img104.jpg
img105.jpg

另一种(长期)解决方案可以是修复Get-ChildItem,使ToString()始终返回相同的结果。这可能被认为是一个突破性的变化,但我怀疑这";bug";已经绊倒了许多用户,甚至那些已经意识到这一点的用户。我知道我一直在忘记。甚至可以让Get-ItemGet-ChildItem使用相同的ToString(),无论是哪一个

对于一个激进的(并且可能引发推论的)解决方案;"修复";Get-ChildItem仅返回子级(或错误),并使dir成为根据需要调用Get-ChildItemGet-Item的函数。这将恢复Powershell的";cmdlet按照他们的名字所说的去做"而不是CCD_ 31有时返回子项,有时返回项目。(太大的突破性变化了,所以我没有屏住呼吸。)

使用PS 5.1.1836.2145进行的试验。

最新更新