PowerShell-准等效字符串实际上并不等效?

PowerShell-准等效字符串实际上并不等效?

我有一个字符串,我将它作为参数传递给我的脚本。但是,为了在此处显示代码,我在代码中手动指定了这些变量。
这些变量是:

  • $SearchFolder
  • $FileType

代码如下:

$SearchFolder = "C:\Users\Name\Downloads"
$FileType = "*.ttf"

#Trim the backslash from the end in case the user adds one in.
$SearchFolder = $SearchFolder.TrimEnd('\')
$FontPathsSearch = $SearchFolder + "\" + $FileType

#For use in debugging.
echo $SearchFolder
echo $FontPathsSearch

$folders = dir -s $FontPathsSearch | Select Directory -Unique | findstr -v -x $SearchFolder
echo $folders

正如所见,在最后一行的末尾,我使用来findstr -v -x $SearchFolder显示所有与(搜索的)根目录不匹配的结果,在本例中为C:\Users\Name\Downloads

但输出如下:

C:\Users\Name\Downloads
C:\Users\Name\Downloads\*.ttf

Directory 
---------    
C:\Users\Name\Downloads\FolderofFont1  
C:\Users\Name\Downloads\FolderofFont2 
C:\Users\Name\Downloads\FolderofFont3 
C:\Users\Name\Downloads          

问题:
从代码输出可以看出,虽然$SearchFolder输出的最后一行看起来相同,但显然它们不是,否则它不会显示。我的想法是,其中可能有一个恶意的空终止符或行尾,但由于我不知道如何使用 PowerShell 进行调试,所以我不能确定。

我想知道的是:
我将如何能够通过当前正在使用的方法(或者通过更好的方法,如果存在的话)从本质上过滤掉主目录。

答案1

看起来您要么是具有丰富的 CMD/Batch 背景的人,要么是正在尝试适应 CMD/Batch 说明/教程。

您可能会遇到的一些问题是,您尝试使用某些命令,就好像它们是从命令提示符而不是 PowerShell 运行的一样。我的意思是,在 PowerShell 中,dir不会运行命令目录而是 PowerShell cmdlet 的别名获取子项

这就是为什么使用/s不起作用并且 PowerShell cmdlet 不接受“/”标志而是“-”参数的原因

因为 PowerShell 团队知道人们会将 dir 与 /s 开关一起使用,所以他们将其添加s为该-Recurse参数的别名,这就是该命令的该部分有效的原因。

抱歉,我一直在谈论这个话题,但我认为一些背景信息可能与之相关。


回到问题本身。PowerShell 正在处理对象并将其对象传递到管道中,直到最终将对象输出到控制台。

findstr命令试图对字符串进行操作(如果您将其精简为字符串,我不能 100%确定它是否会对来自 PowerShell 管道的输入进行操作。)

我建议不要使用该命令,而是使用Where-Object(或更简单的是它的别名在哪里

第一反应是这样做:

| Where -FilterScript { $_.Directory -ne $SearchFolder }
# (Directory property 'Not Equal' variable)

但您会发现,Directory 属性中存储的数据实际上比写入控制台时看到的数据要多。

Name        MemberType   Definition                                                                             
----        ----------   ----------                         
Directory   NoteProperty DirectoryInfo Directory=C:\Users\name\Downloads\FolderofFont1

有两个选项可以解释这些额外数据,使用通配符:

| Where -FilterScript { $_.Directory -notlike "*$SearchFolder" }
# (Directory property 'Not Like' variable with a wildcard)

或者,测试不同的属性,它只是问题中的字符串:

| Where -FilterScript { $_.DirectoryName -ne $SearchFolder }
# (Directory Name property 'Not Equal' variable)

但是,如果您使用 DirectoryName 方法,则需要将其放在 Select 语句之前,因为如果您已将对象限制为仅目录,则该属性将不可用。


这是最终结果:

...
$folders = Get-ChildItem -Path $FontPathsSearch -Recurse | Select Directory -Unique | Where -FilterScript { $_.Directory -notlike "*$SearchFolder" }
$folders

Directory                                                                                          
---------                                                                                          
C:\Users\name\Downloads\bootstrap-3.3.4-dist\bootstrap\fonts                                    
C:\Users\name\Downloads\dashboards-gh-pages\dashboards-gh-pages\assets\lib\bootstrap\dist\fonts 
C:\Users\name\Downloads\dashboards-gh-pages\dashboards-gh-pages\assets\lib\bootstrap\fonts      
C:\Users\name\Downloads\klimato-dashing-widget-master\klimato-dashing-widget-master\assets\fonts
C:\Users\name\Downloads\solar-theme-jekyll-master\solar-theme-jekyll-master\assets\fonts 

很抱歉,这个回答比我预期的要长得多,我希望它有意义。我认为提供一些背景信息以及这一切的来龙去脉会比仅仅说“这是一个对你有用的代码片段”更有用。

另外,我觉得有必要提一下,在 PowerShell 中echo有一个别名,Write-Host被认为是不好的做法。显然,它对您的调试信息很有用,但是在返回结果时,您只需调用该变量即可。

这让人回想起 PowerShell 的全部内容都是对象。返回对象(尤其是作为函数的一部分)意味着您可以继续将数据作为对象进行操作,但是如果您通过 Write-Host 运行它,它将转换为字符串,这意味着您只能将其作为字符串进行操作,从而限制了它的可移植性。

相关内容