Powershell SQLCMD 无法识别输入文件 - 通过路径将通过 Get-ChildItem 获取的文件传递给外部程序

Powershell SQLCMD not recognizing inputfile - passing files obtained via Get-ChildItem to external programs by path

我有这段代码,它获取当前目录中的所有 *.sql 文件以及每个子目录 运行 将它们放在指定的 $server$database:

$dirs = Get-ChildItem | ?{ $_.PSIsContainer }
foreach ($d in $dirs)
{    
    $Result = Get-ChildItem ./ -Filter *.sql
    Foreach($item in $Result)
    {
        echo $item.Name
        sqlcmd /S $server /d $database -E -i $item
    }
}

这段代码工作得很好,但它只是通往脚本的垫脚石,该脚本应该获取 子目录 和 [= 中的所有 *.sql 文件39=] 他们在服务器上。

这段代码是一样的,区别是./$d替换了,不生效:

$dirs = Get-ChildItem | ?{ $_.PSIsContainer }
foreach ($d in $dirs)
{
    $Result = Get-ChildItem $d -Filter *.sql
    Foreach($item in $Result)
    {
        echo $item.Name
        sqlcmd /S $server /d $database -E -i $item
    }
}

相反,我得到了错误:
SQLCMD.EXE : Sqlcmd: 'INSERT Script1.sql': Invalid filename. At E:\dir\Run all SQL in dir.ps1:23 char:12 + sqlcmd <<<< /S $server /d $database -E -i $item + CategoryInfo : NotSpecified: (Sqlcmd: 'INSERT...valid filename.:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError

据我从测试中可以看出,$item 在这两种情况下都是相同的,$Result 看起来也一样。

我不知道为什么第二个版本不起作用。我希望脚本遍历它所在的当前目录的所有子目录,获取每个文件中的所有 *.sql 文件,打印文件名并 运行 它针对集合 $server$database.

$item 是一个 [FileInfo] 对象。

更改为 $item.FullName,其中将包含完整的文件路径。

我假设第一个版本有效,因为该文件位于同一目录中。

添加到

[System.IO.FileInfo][System.IO.DirectoryInfo]Get-ChildItem / Get-Item 输出的实例通常 字符串化到 仅文件名 (.Name) 而不是 完整路径 (.FullName),其中,结合 PowerShell 的参数绑定,可能会导致细微的错误:

注意:我在这里松散地使用文件名来指代文件名和目录名;换句话说:file-system 项的名称。

  • 将这样的实例传递给外部程序,就像您的情况一样,然后仅传递文件名 , 因为 外部程序的所有参数都 隐式字符串化 .

    • 在这种情况下使用 .FullName 确实是正确的解决方案。
  • 然而,更令人惊讶的是,该问题还影响 cmdlet / 函数调用:

    • 在您的代码中,Get-ChildItem $d 中的 $d 作为 字符串 [=82] 传递=] 因此仅作为文件名,因为 - 不幸的是 - -Path 参数将其 direct 参数绑定为 strings 而不是识别 [System.IO.FileInfo] / [System.IO.DirectoryInfo] 实例;相比之下,通过 管道 传递此类实例可以正常工作。

    • 因此,即使 $d 明确标识了一个给定的目录,也只有它的 name 被传递,最多 发生 工作,最坏情况下 指向不同的目录 ,否则 失败 .

      • 这里使用.FullName也可以绕过问题:Get-ChildItem $d.FullName
    • 这个问题已经 reported on GitHub,我鼓励任何对修复感兴趣的人在那里发表他们的意见。
      关于向后兼容性的说明:更改 [System.IO.FileInfo][System.IO.DirectoryInfo] 字符串化的方式(字符串化为它们的 .FullName 属性 值)可能太破坏了更改,但是按照描述更改参数绑定在链接的 GitHub 问题中非常值得考虑,因为当前的行为基本上被破坏了。