[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文件操作] 多个可独自运行的批处理文件组成一个大的批处理,为何大批处理文件不能顺利运行

各位大神好,我编写一个数据处理程序,因为比较复杂,分成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

不知大神们对组合批处理在一起运行上,有何改进建议?多谢多谢

我感觉是时间太快,不够反应,能不能适当给点延时。

TOP

回复 1# delab-1

一。先看每个小批最后一个命令/语句的返回值,系统内置命令和系统原生程序均有返回值,但第三方程序不一定都有返回值,如果没有返回值,系统变量 errorlevel 会保持原值
二。大批中每个链接句式的 errorlevel 对应前一个小批最后一个命令/语句的返回值,只有=1时,pause 才会生效

TOP

楼主说的停下来不知道是异常退出了还是报错了?
观察下哪个bat异常,把它发出来
或者可以从变量冲突方面考虑,用区域变量避免,如果多个bat共用变量,那又复杂了。
bat小白,请多指教!谢谢!

TOP

本帖最后由 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
                         )

此外,我做了测试,如果把所有的批处理内容放在一个文件中(不是分开写不同的批处理,而是把所有的内容拷贝到一个文件中),整个程序是没有问题的,可以完全执行成功。但是把它们拆开后,上面的这个程序就不能回到根目录下,导致后续子批处理没法运行。

TOP

本帖最后由 77七 于 2024-8-21 14:58 编辑

回复 5# delab-1


     批处理文件作为子过程默认endlocal,setlocal与endlocal之间的pushd,popd作为区域变量,随着子过程结束而失效。
bat小白,请多指教!谢谢!

TOP

本帖最后由 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
                                )

TOP

加入在循环部分,popd之前加入 setlocal disabledelayedexpansion 也没有用处,还是不行。

TOP

回复 6# 77七


    看来只能在程序之外加入额外命令,保持子程序在正确目录中调用了。不是是否还有其他破解之法?

TOP

回复 5# delab-1

要确认 pushd .\2017 和 pushd ..\2017 的区别,前者运行成功要求2017须为当前目录的 ‘子目录’,后者运行成功要求2017须与当前目录为 ‘同级目录’

TOP

回复 9# delab-1


  不改动子bat代码, 和此贴类似, call 前后使用区域变量
bat小白,请多指教!谢谢!

TOP

5楼代码
  1. pushd ..\%%a %有效%
  2. setlocal enabledelayedexpansion
  3. popd %失效%
  4. pushd ..\%%a %失效%
  5. setlocal enabledelayedexpansion
  6. popd %失效%
  7. ...
  8. endlocal %默认隐形%
  9. endlocal %默认隐形%
复制代码


如果修改子bat,只需要在第一个 pushd之前,或者直接在代码开头加一个setlocal,这时候 第一个pushd也成为区域变量了。
bat小白,请多指教!谢谢!

TOP

回复 12# 77七


   感谢感谢,在前面加入setlocal 后,后面的问题就完美解决了 :handshake 。非常感谢!!!

TOP

返回列表