通过字符串变量传递 Powershell Get-ChildItem 过滤器参数不起作用

Passing Powershell Get-ChildItem filter parameter through a string variable is not working

在我的脚本中,我有以下函数 returns 一个字符串作为“*.csproj”、“*.vbproj”、“*.sln”。假设我总是将 "csproj, vbproj, sln" 之类的字符串传递给 $filter 参数:

Function Create-Filter($filter)
{    
    $str = $filter.Split(',') | ForEach-Object {"""*.$($_.Trim())"""}

    $str = $str -join ', '
    [string]$str
    return
}

稍后在我的脚本中执行:

$filter = Create-Filter($filter)
$myFiles = Get-ChildItem $source -Include $filter -Recurse  

但是 $myFiles 是空的,Get-ChildItem 没有返回任何东西。我知道问题出在传递给 Get-ChildItem 时的 $filter 参数中,但我不知道如何解决这个问题。

无论如何,从 powershell 控制台,如果我在下面做它有效:

PS > $filter = "*.csproj", "*.vbproj", "*.sln"
PS > Get-ChildItem "D:\Path\To\My\Root\Folder" -Include $filter -Recurse

那我做错了什么?

我的powershell版本如下图所示:

更新(解决方案): AdminOfThings 提出的解决方案有效。 在我的例子中,应用 AdminOfThings 不起作用,因为我在我的代码中犯了一个错误。我将 Create-Filter 函数返回的值分配给与我作为参数传递的变量相同的变量,如下所示:

$filter = Create-Filter ($filter)
Get-ChildItem "D:\Path\To\My\Root\Folder" -Include $filter -Recurse

为了让它发挥作用,我做了以下工作:

$formattedfilter = Create-Filter ($filter)
Get-ChildItem "D:\Path\To\My\Root\Folder" -Include $formattedfilter -Recurse

...也就是说,使用不同的变量按函数分配返回值,而不是使用我作为参数传递的变量。

简而言之,您需要从函数中删除文字引号(将三重双引号替换为单双引号)、-Join 和字符串转换 ([string])。基本上,任何将输出字符串化的内容都需要删除。

Function Create-Filter($filter)
{    
    $filter.Split(',') | ForEach-Object {"*.$($_.Trim())"}
    return
}

-Include 参数接受单个字符串或字符串数​​组。当您传递 -Include "string1","string2" 时,您将一个字符串数组传递到命令中。在您的过滤器中,您正在创建一个包含文字引号和逗号的字符串。这里的微妙之处在于在引号中包含逗号会创建一个包含引号的字符串,而引号 BETWEEN 逗号会创建一个逗号分隔的字符串列表。如此有效,该命令正在读取 -Include '"string1","string2"',它什么也找不到。即使您的函数输出的文本看起来与您直接在命令中键入的内容相同,PowerShell 也会以不同的方式解释这些值。

您可以在下面看到您的函数输出被 PowerShell 解释为单个字符串的行为。

create-filter ("txt","csv")
"*.txt", "*.csv"
(create-filter ("txt","csv")).gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

下面的数组语法(逗号分隔的字符串类型列表)输出不同的结果。

"*.txt","*.csv"
*.txt
*.csv
("*.txt","*.csv").gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

执行代码:

$str = "txt,csv"
create-filter $str
*.txt
*.csv
$filter = create-filter $str
Get-ChildItem . -Include $filter -Recurse
    Directory: C:\temp\test1


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         6/8/2019  10:47 AM             68 -44.csv
-a----         6/8/2019  10:47 AM            101 -54.csv
-a----        6/11/2019   8:50 AM            229 count.txt
-a----        6/11/2019   8:58 AM            170 destination.txt
-a----        6/11/2019   8:53 AM            302 f.txt
-a----        6/12/2019   6:36 AM            294 hashash.txt
-a----         6/6/2019   1:14 PM              4 jaf.csv
-a----         6/6/2019   1:31 PM              0 job1.txt

嗯,我会使用更快的 -filter。

ls -r D:\Path\To\My\Root\Folder -filter *.csproj,*.vbproj,*.sln

编辑:噢,那行不通。但这确实如此。我不确定你需要这个功能做什么。

ls -r D:\Path\To\My\Root\Folder -include *.csproj,*.vbproj,*.sln

$source = 'D:\Path\To\My\Root\Folder'
$filter = '*.csproj','*.vbproj.*','*.sln' # or
$filter = echo *.csproj,*.vbproj,*.sln 

ls -r $source -include $filter