代码之家  ›  专栏  ›  技术社区  ›  FMFF

带有通配符字符串数组的PowerShell Get-ChildItem

  •  1
  • FMFF  · 技术社区  · 10 月前

    我有一个文件夹,里面有一堆SQL Server。几个数据库的BAK文件。这个BAK文件名每天都在变化。

    其中,我只对3-4个数据库感兴趣 最近的 的BAK文件 Restore-SqlDatabase .

    到目前为止,我所拥有的是:

    $databases = @('Orders', 'Items', 'Returns')
    $BackupPath  = '\\BACKUPSERVER\BackupData\'
    $latestBackupFile = Get-ChildItem $BackupPath -Attributes !Directory *$databases[0]* | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1
    $latestBackupFile
    #Restore-SqlDatabase -ServerInstance "my-vm" -Database "Orders" -BackupFile "\\BACKUPSERVER\BackupData\AODA2.Orders.2024-01-15.22-23-13.BAK" -ReplaceDatabase
    #Restore-SqlDatabase -ServerInstance "my-vm" -Database "Items" -BackupFile "\\BACKUPSERVER\BackupData\MMMWW.Items.2024-01-15.22-23-13.BAK" -ReplaceDatabase
    

    这个 还原SqlDatabase 命令在自己执行时正在工作;我在上面的脚本中包含了上下文。

    *$databases[0]* -这不会产生像这样的通配符字符串 *Orders* 正如我所希望的那样。

    我不知道如何为制作ForEach循环 a) 循环通过 $databases 数组以获得通配符字符串,如 *订单* , *Items* , *Returns* 等 和 b) 循环浏览最新消息。用于构建的每个通配符的BAK文件 还原SqlDatabase 命令

    我是PowerShell新手;如何做到这一点?非常感谢。

    1 回复  |  直到 10 月前
        1
  •  3
  •   Mathias R. Jessen    10 月前

    PowerShell有两种不同的语法,在文档中描述为 "parsing modes" :

    • 参数模式:
      • 应用于命令名后面的所有内容,包括 *$database[0]* 论点
    • 表达式模式:
      • 适用于大多数其他方面,并完全按照您的预期工作: $databases[0] 将被解释为数组索引操作

    当PowerShell在参数模式下遇到所谓的“裸词令牌”时,它会自动将其解释为可扩展字符串文字表达式的内容。

    换句话说,论点 *$databases[0]* 被解释为与你写的一样 "*$databases[0]*" .

    在可扩展字符串文字中,仅 简单变量表达式 被识别并展开-因此PowerShell尝试评估 $databases 不考虑 [0] .

    可以通过使用子表达式运算符包装表达式来转义字符串插值规则 $() :

    "*$($databases[0])*"
    

    很高兴知道, 但你在这里并不真的需要它 -你需要一个循环!

    我不知道如何制作ForEach循环

    这个 foreach loop statement 在PowerShell中相当简单:

    foreach ($item in $collection) {
      # work with each $item here
    }
    

    让我们试试你的 $数据库 大堆

    foreach ($databaseName in $databases) {
      # find the latest backup file containing the db name in its file name
      $latestBackupFile = Get-ChildItem $BackupPath -File -Filter "*$databaseName*.bak" | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1
    
      if ($latestBackupFile) {
        Restore-SqlDatabase -ServerInstance "my-vm" -Database $databaseName -BackupFile $latestBackupFile.FullName -ReplaceDatabase
      }
      else {
        Write-Warning "Unable to locate backup file for database $databaseName"
      }
    }
    

    由于我们不再依赖数组索引器, $databaseName 现在可以按预期在过滤器字符串中展开-在第一次迭代中 $databaseName 变量将具有值 "Orders" ,所以参数表达式 -Filter "*$databaseName*.bak" 将产生筛选器字符串 *Orders*.bak

    最后,如果您需要用字符填充数据库名称,否则这些字符可能会被解释为变量路径的一部分,则可以使用限定变量路径 {} :

    # underscore _ below would have been interpreted as part of the variable path expression `$databaseName_` if not for the curly brackets
    ... -Filter "*${databaseName}_*.bak"