PowerShell中SQLCMD无法识别输入文件:传递Get-ChildItem获取的文件路径
搞定递归执行子目录SQL脚本的问题
嘿,我看了你的脚本,现在帮你调整成能遍历所有子目录执行SQL的版本,顺便解决sqlcmd识别不了文件的问题~
首先说下你当前脚本的两个小问题:
- 你虽然循环了子目录,但里面的
Get-ChildItem ./ -Filter *.sql一直只拿当前目录的SQL文件,根本没进到子目录里去读 - 直接把
$item传给sqlcmd的-i参数,PowerShell可能会把它当成对象而非文件路径,导致sqlcmd找不到文件
下面是修正后的完整脚本,直接就能用:
# 递归抓取当前目录及所有子目录下的所有.sql文件 $sqlFiles = Get-ChildItem -Path . -Filter *.sql -Recurse -File foreach ($item in $sqlFiles) { # 打印当前执行的脚本路径,方便排查问题 Write-Host "正在执行: $($item.FullName)" # 用完整路径传给sqlcmd,彻底解决路径识别问题 sqlcmd /S $server /d $database -E -i "$($item.FullName)" }
为啥这么改?给你拆解下:
- 加了
-Recurse参数,Get-ChildItem就会自动钻进所有子目录找文件,不用你手动循环目录了 -File参数确保只拿文件,不会把目录也混进来,避免报错- 用
$item.FullName代替直接传$item,sqlcmd需要明确的完整路径,这样就不会出现“找不到文件”的问题了 - 把
echo换成Write-Host,在PowerShell里这个更适合控制台输出,echo其实是Write-Output的别名,会把输出丢进管道,这里没必要
如果你特别想保留“先处理A目录所有脚本,再处理B目录”的顺序(而不是按文件递归顺序),可以用这个版本:
# 获取所有子目录,包括嵌套的 $allDirs = Get-ChildItem -Path . -Directory -Recurse # 把当前目录也加进去,要是你想先执行当前目录的脚本的话 $allDirs += Get-Item . foreach ($dir in $allDirs) { Write-Host "===== 处理目录: $($dir.FullName) =====" # 只拿当前目录下的SQL文件,不递归(因为已经遍历所有目录了) $sqlFiles = Get-ChildItem -Path $dir.FullName -Filter *.sql -File foreach ($item in $sqlFiles) { Write-Host "执行脚本: $($item.Name)" sqlcmd /S $server /d $database -E -i "$($item.FullName)" } }
要是还出问题,你可以这么排查:
- 先打印
$item.FullName看看路径对不对,是不是真的存在这个文件 - 确认
$server和$database变量已经正确赋值了,别连错数据库 - 要是权限不够,把
-E换成-U 你的用户名 -P 你的密码就行
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

