我有一个字符串,我将它作为参数传递给我的脚本。但是,为了在此处显示代码,我在代码中手动指定了这些变量。
这些变量是:
$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 运行它,它将转换为字符串,这意味着您只能将其作为字符串进行操作,从而限制了它的可移植性。