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

岁酱吖の 提交于 2019-12-11 06:15:31

问题


In my script I have below function that returns a string as "*.csproj", "*.vbproj", "*.sln". Assuming I always pass a string such as "csproj, vbproj, sln" to $filter parameter:

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

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

Later in my script I perform:

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

But $myFiles is empty, Get-ChildItem is not returning anything. I know that the problem is in $filter parameter when passing to Get-ChildItem but I do not know how to solve this.

Anyway, from powershell console, If i do below It works:

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

So what am I doing wrong?

My powershell version is as below image shows:

UPDATE (SOLUTION): Solution proposed by AdminOfThings works. In my case applying AdminOfThings was not working because I did a mistake in my code. I was assigning the value returned by Create-Filter function into the same variable as that I was passing as argument, like below:

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

In order to make it work I have done below:

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

...that is, using a different variable to assign returned value by function instead of using the same as that I was passing as argument.


回答1:


In short, you need to remove the literal quotes (replace triple double quotes with single double quotes), the -Join, and the string casting ([string]) from your function. Basically, anything that stringifies your output, needs to be removed.

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

The -Include parameter accepts a single string or an array of strings. When you pass -Include "string1","string2", you are passing an array of strings into the command. In your filter, you are creating one string that includes literal quotes and commas. The subtlety here is including the commas within the quotes creates a string that contains quotes whereas quotes BETWEEN commas creates a comma separated list of strings. So effectively, the command is reading -Include '"string1","string2"', which will find nothing. Even though your function outputs text that looks identical to what you would type directly into the command, PowerShell will interpret those values differently.

You can see the behavior below where the output of your function is interpreted by PowerShell as a single string.

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

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

The array syntax (comma separated list of string types) below outputs a different result.

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

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

Executing the Code:

$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



回答2:


Hmm, I would use -filter which is faster.

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

EDIT: Aww, that doesn't work. But this does. I'm not sure what you need the function for.

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

or

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

ls -r $source -include $filter


来源:https://stackoverflow.com/questions/56621552/passing-powershell-get-childitem-filter-parameter-through-a-string-variable-is-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!