Powershell SQLCMD无法识别输入文件 - 通过路径

时间:2018-03-27 13:22:18

标签: powershell scripting filepath get-childitem

我有这个代码,它获取当前目录中的所有* .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文件并在服务器上运行它们。

此代码与./替换为$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和{{1 }}

2 个答案:

答案 0 :(得分:2)

$item[FileInfo]个对象。

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

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

答案 1 :(得分:1)

添加到gms0ulman's helpful answer

[System.IO.FileInfo][System.IO.DirectoryInfo]实例按Get-ChildItem / Get-Item输出通常仅字符串化为文件名.Name而不是完整路径.FullName),与PowerShell的参数绑定结合使用,会导致微妙的错误

注意:我在这里松散地使用文件名来引用文件的名称和目录的名称;换句话说:文件系统项目的名称。

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

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

    • 在您的代码中,$d中的Get-ChildItem $d 作为字符串传递,因此仅作为文件名,因为 - 不幸的是 - -Path参数将直接参数绑定为字符串 ,而不是识别[System.IO.FileInfo] / {{1这样的实例;相反,通过管道传递此类实例的工作正常。

    • 因此,即使[System.IO.DirectoryInfo]明确标识给定目录,也只传递其名称,最好发生才能工作,最差定位到不同的目录,否则失败

      • 在这里使用$d也会绕过问题:.FullName
    • 这个问题一直是reported on GitHub,我鼓励任何对修复感兴趣的人都能在那里听到他们的声音。
      关于向后兼容性的注释:更改Get-ChildItem $d.FullName[System.IO.FileInfo] stringify的方式(字符串化为[System.IO.DirectoryInfo]属性值)可能会破坏更改,但更改参数绑定,如链接的GitHub中所述鉴于目前的行为基本上已被打破,这个问题值得考虑。