批处理脚本从文件中删除BOM()

问题描述 投票:0回答:3

我创建了一个批处理脚本,将SQL文件从一个文件夹复制到一个大的SQL脚本中。问题是,当我运行这个SQL脚本时,它会出现错误

“'附近的语法不正确

我将一个SQL脚本复制到Notepad ++中,并将编码设置为ANSI。我在发生错误的行上看到了这个符号(BOM)。

无论如何,我可以在我的批处理脚本中自动删除它。我不希望每次运行此任务时都手动删除它。

下面是我目前的批处理脚本

@echo off

set "path2work=C:\StoredProcedures"
cd /d "%path2work%"

echo. > C:\FinalScript\AllScripts.sql

for %%a in (*.sql) do (

    echo. >>"C:\FinalScript\AllScripts.sql"
    echo GO >>"C:\FinalScript\AllScripts.sql"
    type "%%a">>"C:\FinalScript\AllScripts.sql"
    echo. >>"C:\FinalScript\AllScripts.sql"
)
batch-file byte-order-mark
3个回答
1
投票

这是因为type命令将保留UTF-8 BOM,因此当您组合具有BOM的多个文件时,最终文件将在文件中间的不同位置包含多个BOM。

如果您确定要组合的所有SQL文件,请从BOM开始,然后您可以使用以下脚本在实际组合它们之前从每个文件中删除BOM。

这是通过管道type的输出来完成的。在3个pause命令的帮助下,管道的另一侧将消耗前3个字节(BOM)。每个pause将消耗一个字节。流的其余部分将发送到findstr命令以将其附加到最终脚本。

由于SQL文件是UTF-8编码的,并且它们可能包含Unicode范围内的任何字符,因此某些代码页将干扰操作,并可能导致最终的SQL脚本损坏。

因此,这已被考虑在内,批处理文件将通过代码页437重新启动,这对于访问任何二进制序列是安全的。

@echo off
setlocal DisableDelayedExpansion


setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('chcp') do for %%b in (%%a) do set "CP=%%~nb"
if  !CP! NEQ 437 if !CP! NEQ 65001 chcp 437 >nul && (

    REM for file operations, the script must restatred in a new instance.
    "%COMSPEC%" /c "%~f0"

    REM Restoring previous code page
    chcp !CP! >nul
    exit /b
)
endlocal


set "RemoveUTF8BOM=(pause & pause & pause)>nul"
set "echoNL=echo("
set "FinalScript=C:\FinalScript\AllScripts.sql"

:: If you want the final script to start with UTF-8 BOM (This is optional)
:: Create an empty file in NotePad and save it as UTF8-BOM.txt with UTF-8 encoding.
:: Or Create a file in your HexEditor with this byte sequence: EF BB BF
:: and save it as UTF8-BOM.txt
:: The file must be exactly 3 bytes with the above sequence.
(
    type "UTF8-BOM.txt" 2>nul

    REM This assumes that all sql files start with UTF-8 BOM
    REM If not, then they will loose their first 3 otherwise legitimate characters.
    REM Resulting in a final corrupted script.
    for %%A in (*.sql) do (type "%%~A" & %echoNL%)|(%RemoveUTF8BOM% & findstr "^")

)>"%FinalScript%"

1
投票

正如MSalters在他的评论中提到的,根据wikipedia是UTF8 BOM的ANSI表示。

与批处理相比,PowerShell更适合处理编码的任务:

## Q:\Test\2018\09\11\SO_522772705.ps1
Set-Location 'C:\StoredProcedures'
Get-ChildItem '*.sql' | ForEach-Object {
    "`nGO"
    Get-Content $_.FullName -Encoding UTF8
    ""
} | Set-Content 'C:\FinalScript\AllScripts.sql' -Encoding UTF8

要使用标签batch-file进行主题,请批量调用powershell作为基本部分:

:: Q:\Test\2018\09\11\SO_522772705..cmd
@echo off
set "path2work=C:\StoredProcedures"
cd /d "%path2work%"

powershell -NoProfile -Command "Get-ChildItem '*.sql'|ForEach-Object{\"`nGO\";Get-Content $_.FullName -Enc UTF8;\"\"}|Set-Content 'C:\FinalScript\AllScripts.sql' -Enc UTF8"

0
投票

您只需将编码更改为UTF-8而不使用BOM并保存文件

Notepad++ BOM

请注意,较旧的Notepad ++版本的菜单项略有不同

© www.soinside.com 2019 - 2024. All rights reserved.