标题: [文件操作] 多个可独自运行的批处理文件组成一个大的批处理,为何大批处理文件不能顺利运行 [打印本页]
作者: delab-1 时间: 2024-8-20 23:10 标题: 多个可独自运行的批处理文件组成一个大的批处理,为何大批处理文件不能顺利运行
各位大神好,我编写一个数据处理程序,因为比较复杂,分成6个步骤,每个步骤由1个小批处理完成。这6个按顺序运行的批处理(即:s1.bat,s2.bat, ......, s6.bat)都是可以成功运行的。
在后续操作中,我把这6个批处理放置在一次,形成一个run_all.bat,但是到中间步骤总是停下来,总是找不到原因。Run_all.bat是这样写的:
call s1.bat
if errorlevel 1 pause
call s2.bat
if errorlevel 1 pause
call s3.bat
if errorlevel 1 pause
call s4.bat
if errorlevel 1 pause
call s5.bat
if errorlevel 1 pause
call s6.bat
if errorlevel 1 pause
不知大神们对组合批处理在一起运行上,有何改进建议?多谢多谢
作者: 宁处理 时间: 2024-8-21 09:00
我感觉是时间太快,不够反应,能不能适当给点延时。
作者: aloha20200628 时间: 2024-8-21 10:19
回复 1# delab-1
一。先看每个小批最后一个命令/语句的返回值,系统内置命令和系统原生程序均有返回值,但第三方程序不一定都有返回值,如果没有返回值,系统变量 errorlevel 会保持原值
二。大批中每个链接句式的 errorlevel 对应前一个小批最后一个命令/语句的返回值,只有=1时,pause 才会生效
作者: 77七 时间: 2024-8-21 11:03
楼主说的停下来不知道是异常退出了还是报错了?
观察下哪个bat异常,把它发出来
或者可以从变量冲突方面考虑,用区域变量避免,如果多个bat共用变量,那又复杂了。
作者: delab-1 时间: 2024-8-21 14:35
本帖最后由 delab-1 于 2024-8-21 14:37 编辑
找到原因了,不知道为什么下面这个程序,在运行后结束依然运行的子目录中(例如,.\2017),并没有随着popd命令回到根目录里面;而后续的批处理都在根目录中,所以找不到相应的批处理,故而无法运行。大神们可否帮我看看,为何下面程序运行后,并未回到批处理所在的目录(我用的pushd+popd的结合)。
for /L %%a in (2017,1,2023) do (
pushd ..\%%a
echo export >temp.txt
echo import >>temp.txt
setlocal enabledelayedexpansion
for /f %%b in (temp.txt) do (
for /f "skip=21" %%c in (map_all_%%b_12.txt) do (
set str=%%c
echo !str:~0,3! >>std_map_%%b_HS2.txt
)
)
popd
)
此外,我做了测试,如果把所有的批处理内容放在一个文件中(不是分开写不同的批处理,而是把所有的内容拷贝到一个文件中),整个程序是没有问题的,可以完全执行成功。但是把它们拆开后,上面的这个程序就不能回到根目录下,导致后续子批处理没法运行。
作者: 77七 时间: 2024-8-21 14:47
本帖最后由 77七 于 2024-8-21 14:58 编辑
回复 5# delab-1
批处理文件作为子过程默认endlocal,setlocal与endlocal之间的pushd,popd作为区域变量,随着子过程结束而失效。
作者: delab-1 时间: 2024-8-21 15:17
本帖最后由 delab-1 于 2024-8-21 15:29 编辑
回复 6# 77七
有没有办法处理呢?在程序中已经每个批处理都让其回到程序所在的目录之下(code)了,在子批处理叠加的文件中,并回到子目录了。我做了改动,强行将其拉回程序所在目录(code),后续运行能顺序运行。
call s1.bat
call s2.bat
::强行拉回到code目录
cd ..\code
call s3.bat
::强行拉回到code目录
cd ..\agg_aug16
call s4.bat
::强行拉回到code目录
cd ..\agg_aug16
call s5.bat
经过上述处理后,程序就可以顺利运行了。但是,有个地方正如您所说,在S1.bat中,程序如下,其中没有使用setlocal enabledelayedexpansion, 就没有出现问题,所以其后的S2.bat可以正常跟随运行。但是,也的确如您所说,凡是使用setlocal enabledelayedexpansion,回到根目录下code的popd就在子批处理后失效了,后面的s2.bat,S3.bat,S4.bat,S5.bat都用了setlocal enabledelayedexpansion,就必须强加cd ..\code 语句,强行将其拉回到程序所在目录。现在的问题是,是否在S2之后的所有程序中,加入endlocal disabledelayedexpansion会不会解决上述问题呢?
if exist ..\2017\*.txt del ..\2017\*.txt
::------------------------------------------
:: S1:writing all com to txt file
::------------------------------------------
goto next
tablo -wfp set_for_map
call LTG set_for_map
:next
for /L %%a in (2017,1,2017) do (
pushd ..\%%a
if exist *.txt del *.txt
copy ..\agg_aug16\set_for_map.exe
copy ..\agg_aug16\set_for_map.axs
copy ..\agg_aug16\set_for_map.axt
copy ..\agg_aug16\set_for_map.cmf
dir all*.har /b/od>temp_list.txt
for /f %%b in (temp_list.txt) do (
copy set_for_map.cmf temp.cmf
strrpc xxxx %%~nb /i /c /s:temp.cmf
set_for_map.exe -cmf temp.cmf
if errorlevel 1 pause
)
popd
)
作者: delab-1 时间: 2024-8-21 15:24
加入在循环部分,popd之前加入 setlocal disabledelayedexpansion 也没有用处,还是不行。
作者: delab-1 时间: 2024-8-21 15:26
回复 6# 77七
看来只能在程序之外加入额外命令,保持子程序在正确目录中调用了。不是是否还有其他破解之法?
作者: aloha20200628 时间: 2024-8-21 15:36
回复 5# delab-1
要确认 pushd .\2017 和 pushd ..\2017 的区别,前者运行成功要求2017须为当前目录的 ‘子目录’,后者运行成功要求2017须与当前目录为 ‘同级目录’
作者: 77七 时间: 2024-8-21 16:04
回复 9# delab-1
不改动子bat代码, 和此贴类似, call 前后使用区域变量
作者: 77七 时间: 2024-8-21 19:06
5楼代码- pushd ..\%%a %有效%
- setlocal enabledelayedexpansion
- popd %失效%
- pushd ..\%%a %失效%
- setlocal enabledelayedexpansion
- popd %失效%
- ...
- endlocal %默认隐形%
- endlocal %默认隐形%
复制代码
如果修改子bat,只需要在第一个 pushd之前,或者直接在代码开头加一个setlocal,这时候 第一个pushd也成为区域变量了。
作者: delab-1 时间: 2024-8-21 22:30
回复 12# 77七
感谢感谢,在前面加入setlocal 后,后面的问题就完美解决了 :handshake 。非常感谢!!!
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |