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

FMF*_*MFF 2 powershell wildcard

我有一个文件夹,其中包含多个数据库的一堆 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
Run Code Online (Sandbox Code Playgroud)

Restore-SqlDatabase命令单独执行时有效;我已将上下文包含在上述脚本中。

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

我不确定如何制作 ForEach 循环:a) 循环遍历数组$databases以获取通配符字符串,如*Orders**Items**Returns*;b) 循环遍历每个通配符的最新 .BAK 文件以构造命令Restore-SqlDatabase

我是 PowerShell 新手;这个怎么做?谢谢。

Mat*_*sen 5

PowerShell 有两种不同的语法,在文档中描述为“解析模式”

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

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

换句话说,该参数的*$databases[0]*解释与您编写的相同"*$databases[0]*"

在可扩展的字符串文字中,仅识别和扩展简单的变量表达式$databases- 因此 PowerShell 尝试自行计算而不考虑[0].

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

"*$($databases[0])*"
Run Code Online (Sandbox Code Playgroud)

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

我不知道如何制作 ForEach 循环

foreachPowerShell 中的循环语句相当简单:

foreach ($item in $collection) {
  # work with each $item here
}
Run Code Online (Sandbox Code Playgroud)

让我们用你的数组试试$databases

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"
  }
}
Run Code Online (Sandbox Code Playgroud)

由于我们不再依赖数组索引器,$databaseName现在可以按预期在过滤器字符串中展开 - 在第一次迭代时,变量$databaseName将具有 value "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" 
Run Code Online (Sandbox Code Playgroud)