Windows batch - Delayed expansion removes exclamation mark

我们两清 提交于 2020-01-05 11:48:09

问题


I wrote batch script to copy CSS files over to a certain directory and the problem is exclamation marks are removed when I open the CSS files in the destination directory.

The original CSS contains styles with exclamation marks such as:

.foo
{
   color: pink !important;
}

My CSS outcome becomes

.foo
{
   color: pink important;
}

I looked into the root cause of this and based on: exclamation point being removed constantly in batch file

But I cannot figure out where I need to disable delayed expansion in my case.

FYI, my batch is doing followings:

  1. for each theme string separated by comma, find start and end of line numbers that matches certain string.

  2. now I have start and end line numbers (example 500 and 1000)

  3. copy the file contents except between line 500 and 1000

  4. the finalized file is copied over to destination directory

Please let me know if you need more clarification, thanks in advance.

Batch (snippet):

set themes=Platinum,Granite,Sun,Sky,Burgundy,Leaf,Twilight,Sharepoint 2010,Sharepoint 2013

rem Directory that contains theme css files
set RUNTIME_DEST=%K2DIR%\K2 SmartForms Runtime\Styles\Themes

REM Do something with each substring

call :parse "%themes%"
goto :eof

:parse
setlocal

for %%a in ("%themes:,=" "%") do (
   call :getLineNumber %%a
)
endlocal
goto :eof

:getLineNumber
setlocal
echo file name is %~1
set filename=%~1
rem Get start and end line numbers of the unwanted section
for /F "delims=:" %%a in ('findstr /N /C:"PickerCollectionThemeStart" "%RUNTIME_DEST%\%filename%.css"') do (
    set start=%%a
)

for /F "delims=:" %%a in ('findstr /N /C:"PickerCollectionThemeEnd" "%RUNTIME_DEST%\%filename%.css"') do (
   set end=%%a
)

if not defined start (
    echo start not defined...
    set start=0
    set end=0
)

echo start val = !start!
echo end val = !end!


call :resetTheme "%filename%" "%start%" "%end%"
endlocal
goto :eof

:resetTheme
setlocal
set filename=%~1
set start=%~2
set end=%~3


echo %fileName%
echo %start%
echo %end%
echo ---------------

rem Create a copy file to modify
xcopy "%RUNTIME_DEST%\%filename%.css" "%cd%\Batch_tmp" /y /z /r

echo creating tmp copy...
rem Rename the file so we can modify and create finalized version
ren "Batch_tmp\%fileName%.css" "%fileName%_tmp.css"

echo coping all line except section...

rem Copy all lines, except the ones in start-end section
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "Batch_tmp\%fileName%_tmp.css"') do (
    if %%a lss %start% echo(%%b
    if %%a gtr %end% echo(%%b
 )) > Batch_tmp\!fileName!.css

echo copying to blackpearl dir
rem Finally move the css over to blackpearl directory

setlocal DisableDelayedExpansion
xcopy "Batch_tmp\%fileName%.css" "%RUNTIME_DEST%"  /y /z /r
endlocal

endlocal
goto :eof

:eof

pause

UPDATE

Below is my solution that works based on the advice. The difference is, as instructed, set EnableDelayedExpansion at the beginning of script to make the effect on entire batch scope then set DisableDelayedExpansion only where it applies.

set themes=Platinum,Granite,Sun,Sky,Burgundy,Leaf,Twilight,Sharepoint 2010,Sharepoint 2013

rem Directory that contains theme css files
set RUNTIME_DEST=%K2DIR%\K2 SmartForms Runtime\Styles\Themes

REM Do something with each substring

call :parse "%themes%"
goto :eof

:parse
setlocal
for %%a in ("%themes:,=" "%") do (
    echo ------------------------
    call :getLineNumber %%a
)
endlocal
goto :eof

:getLineNumber
setlocal
echo file name is %~1
set filename=%~1
rem Get start and end line numbers of the unwanted section
for /F "delims=:" %%a in ('findstr /N /C:"PickerCollectionThemeStart" "%RUNTIME_DEST%\%filename%.css"') do (
    set start=%%a
)

for /F "delims=:" %%a in ('findstr /N /C:"PickerCollectionThemeEnd" "%RUNTIME_DEST%\%filename%.css"') do (
   set end=%%a
)

if not defined start (
    echo start not defined...
    set start=0
    set end=0
)

echo start val = !start!
echo end val = !end!


call :resetTheme "%filename%" "%start%" "%end%"
endlocal
goto :eof

:resetTheme
setlocal
set filename=%~1
set start=%~2
set end=%~3

echo %fileName%
echo %start%
echo %end%

rem Create a copy file to modify
xcopy "%RUNTIME_DEST%\%filename%.css" "%cd%\Batch_tmp" /y /z /r

echo creating tmp copy...
rem Rename the file so we can modify and create finalized version
ren "Batch_tmp\%fileName%.css" "%fileName%_tmp.css"

echo coping all line except section...

rem Copy all lines, except the ones in start-end section
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "Batch_tmp\%fileName%_tmp.css"') do (
    setlocal DisableDelayedExpansion
    if %%a lss %start% echo(%%b
    if %%a gtr %end% echo(%%b
    endlocal
 )) > Batch_tmp\!fileName!.css

echo copying to blackpearl dir
rem Finally move the css over to blackpearl directory

xcopy "Batch_tmp\%fileName%.css" "%RUNTIME_DEST%"  /y /z /r

endlocal
goto :eof

:eof

回答1:


I'd put it here were I you...

(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "Batch_tmp\%fileName%_tmp.css"') do (
    SETLOCAL DISABLEDELAYEDEXPANSION
    if %%a lss %start% echo(%%b
    if %%a gtr %end% echo(%%b
    ENDLOCAL
 )) > Batch_tmp\!fileName!.css

but no guarantees...


Disappointing results reported by OP :(

Here's my test setup:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: force directories, start and end
SET runtime_dest=c:\temp
SET filename=test
SET start=2
SET end=4

:: create batch_temp & clear

MD "%cd%\Batch_tmp" 2>NUL >NUL
DEL "%cd%\Batch_tmp\*?*" /F /Q

:: make copy of original .css
xcopy "%RUNTIME_DEST%\%filename%.css" "%cd%\Batch_tmp" /y /z /r

echo creating tmp copy...
rem Rename the file so we can modify and create finalized version
ren "Batch_tmp\%fileName%.css" "%fileName%_tmp.css"

echo coping all line except section...
rem Copy all lines, except the ones in start-end section
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "Batch_tmp\%fileName%_tmp.css"') do (
    if %%a lss %start% echo(%%b
    if %%a gtr %end% echo(%%b
 )) > Batch_tmp\!fileName!.css
rem Copy all lines, except the ones in start-end section
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "Batch_tmp\%fileName%_tmp.css"') do (
SETLOCAL disabledelayedexpansion
    if %%a lss %start% echo(%%b
    if %%a gtr %end% echo(%%b
ENDLOCAL
 )) > Batch_tmp\!fileName!WITHSETLOCAL_ENDLOCAL.css

ECHO ============================
ECHO Batch_tmp\%fileName%_tmp.css
TYPE Batch_tmp\%fileName%_tmp.css
ECHO =======^^^^^^^^=================this is the original file
ECHO Batch_tmp\%fileName%.css
TYPE Batch_tmp\%fileName%.css
ECHO =======^^^^^^^^=================this is the result with delayed expansion enabled
ECHO Batch_tmp\%fileName%WITHSETLOCAL_ENDLOCAL.css
TYPE Batch_tmp\%fileName%WITHSETLOCAL_ENDLOCAL.css
ECHO ========^^^^^^^^================this is the result with the advised setlocal/ENDLOCAL IN place
GOTO :eof

And results:

C:\temp\test.css
1 File(s) copied
creating tmp copy...
coping all line except section...
============================
Batch_tmp\test_tmp.css
.foo
omit me
and me
and me
{
   color: pink !important;
}
=======^^^^=================this is the original file
Batch_tmp\test.css
.foo
{
   color: pink important;
}
=======^^^^=================this is the result with delayed expansion enabled
Batch_tmp\testWITHSETLOCAL_ENDLOCAL.css
.foo
{
   color: pink !important;
}
========^^^^================this is the result with the advised setlocal/ENDLOCAL IN place

So - all I can say is "Works for me!"



来源:https://stackoverflow.com/questions/17370488/windows-batch-delayed-expansion-removes-exclamation-mark

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!