简体   繁体   English

Powershell 脚本自动化 gci

[英]Powershell script to automate gci

I'm tying to automate gci in order to work on each row in a config file, where for each row I have as first column the path, and following it a list of files.我正在尝试自动化 gci,以便在配置文件中的每一行上工作,对于每一行,我将路径作为第一列,然后是文件列表。 Something like this:像这样的东西:

C:\Users\*\AppData\Roaming\* *.dll
C:\Test file.txt,file2.txt

This means that gci will search for: *.dll in C:\Users*\AppData\Roaming* file.txt in C:\Test file2.txt in C:\Test This means that gci will search for: *.dll in C:\Users*\AppData\Roaming* file.txt in C:\Test file2.txt in C:\Test

In order to do this I'm creating dynamically the where condition in the script below.为了做到这一点,我在下面的脚本中动态创建 where 条件。 Here the ps script I'm using这是我正在使用的 ps 脚本

foreach($line in Get-Content .\List.txt) {
       
    try {
        $path,$files = $line.split(' ')
        $files = $files.split(',')
    }
    catch {
        $path = $line
        $files = "*.*"
    }
        
    if([string]::IsNullOrEmpty($files)){
        $files = "*.*"
    }
    
    $filter = $files -join(" -or `$_.Name` -like ")
    $filter = "`$_.Name` -like " + $filter
                
    echo "Searching Path: $path, Pattern: $filter" | out-file -append -encoding ASCII -filepath .\result.txt
        
    if ($path.Contains("*"))
    {
        gci -Path $path -Recurse | Where {$filter} | Select -ExpandProperty FullName | Out-String -Width 2048 | out-file -append -encoding UTF8 -filepath .\result.txt
    }
    else
    {
        gci -Path $path | Where {$filter} | Select -ExpandProperty FullName | Out-String -Width 2048 | out-file -append -encoding UTF8 -filepath .\result.txt
    }
}

The problem is that the where filter is not considered.问题是没有考虑 where 过滤器。 All files are returned返回所有文件

First attempt , suggested by第一次尝试,建议

foreach($line in Get-Content .\List.txt) {
    try {
        $path,$files = $line.split(' ')
        $files = $files.split(',')
    }
    catch {
        $path = $line
        $files = "*.*"
    }
        
    if([string]::IsNullOrEmpty($files)){
        $files = "*.*"
    }

    $filter = $files -join(" -or `$_.Name -like ")
    $filter = "`$_.Name -like " + $filter 

    $gciParams = @{
        Path = $Path
        Recurse = $Path.Contains('*')
    }

    "Searching Path: $path, Pattern(s): [$($files -join ',')]" | Add-Content -Path .\result.txt -Encoding ASCII
        
    Get-ChildItem @gciParams | Where $filter | Select -ExpandProperty FullName | Add-Content -Path .\result.txt -Encoding UTF8
}

If you want to create a piece of code and defer execution of it until later , you need a Script Block .如果您想创建一段代码并将其推迟到以后执行,您需要一个脚本块

A Script Block literal in PowerShell is just {} , so for constructing script block to filter based on a single comparison, you'd want to define $filter like this: PowerShell 中的脚本块文字只是{} ,因此要构建脚本块以基于单个比较进行过滤,您需要像这样定义$filter

$filter = {$_.Name -like $filter}

At which point you can pass it directly as an argument to Where-Object :此时您可以将其作为参数直接传递给Where-Object

Get-ChildItem $path |Where-Object $filter

... but since you want to test against multiple wildcard patterns, we'll need to write a slightly different filtering routine: ...但是由于您想针对多个通配符模式进行测试,我们需要编写一个稍微不同的过滤例程:

$filter = {
  # Store file name of file we're filtering
  $FileName = $_.Name

  # Test ALL the patterns in $files and see if at least 1 matches
  $files.Where({$FileName -like $_}, 'First').Count -eq 1
}

Since the $filter block now references $files to get the patterns, we can simplify your loop as:由于$filter块现在引用$files来获取模式,我们可以将您的循环简化为:

foreach($line in Get-Content .\List.txt) {
    try {
        $path,$files = $line.split(' ')
        $files = $files.split(',')
    }
    catch {
        $path = $line
        $files = "*.*"
    }
        
    if([string]::IsNullOrEmpty($files)){
        $files = "*.*"
    }

    $gciParams = @{
        Path = $Path
        Recurse = $Path.Contains('*')
    }

    "Searching Path: $path, Pattern(s): [$($files -join ',')]" | Add-Content -Path .\result.txt -Encoding ASCII
        
    Get-ChildItem @gciParams | Where $filter | Select -ExpandProperty FullName | Add-Content -Path .\result.txt -Encoding UTF8
}

Note that we no longer need to re-define $filter everytime the loop runs - the condition is based on the value of $files at runtime, so you can define $filter once before entering the loop and then reuse $filter every time.请注意,我们不再需要在每次循环运行时重新定义$filter - 条件是基于运行时$files的值,因此您可以在进入循环之前定义一次$filter ,然后每次重用$filter

The "trick" with using @gciParams (which allows us to remove the big if/else block) is known as splatting , but you could achieve the same result with Get-ChildItem -Path:$Path -Recurse:$Path.Contains('*') :)使用@gciParams的“技巧”(它允许我们删除大的if/else块)被称为splatting ,但您可以使用Get-ChildItem -Path:$Path -Recurse:$Path.Contains('*') :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM