批处理脚本for循环处理含感叹号路径时的延迟扩展问题求助
批处理脚本for循环处理含感叹号路径时的延迟扩展问题求助
我知道社区里已经有不少关于这个问题的提问,但我刚接触批处理脚本,那些解决方案要么很难适配我的场景,要么完全不适用。有人说可以临时禁用延迟扩展来解决含!的路径问题,但我试过之后整个脚本就完全没法运行了。
我的脚本需求与原有实现
先说说我的脚本要实现的功能:
- 遍历指定源文件夹(包括所有子文件夹)下的每一个文件
- 检查该文件是否在目标文件夹中存在
- 如果不存在则分两种情况处理:
- 若是
.png/.jpg/.mp4格式,直接将源文件复制到目标对应路径 - 其他格式则创建同名的0字节空文件(我用xcopy复制一个现成的空dummy文件来实现,因为这种方式处理特殊字符没出过问题)
- 若是
以下是最初能正常工作,但遇到含!路径就出错的脚本:
@echo off setlocal EnableExtensions EnableDelayedExpansion rem Set the source and destination folders set "src=L:\folderS\sub1\sub2" set "dst=L:\folderD\sub1" rem Set the path to the dummy file that we need to create dummy files with xcopy set "dummy=L:\dummy.txt" rem Create the destination folder if it doesn't exist if not exist "%dst%" mkdir "%dst%" rem Loop through all the files in the source folder for /R "%src%" %%f in (*) do ( rem Get the file path set "filePath=%%f" echo the full path is !filePath! rem Get the file extension set "ext=%%~xf" rem Get the relative path excluding the path until the specified src folder set "relPath=!filePath:%src%\=!" echo the relative path is !relPath! rem Check if the file does not exist in the destination if not exist "%dst%\!relPath!" ( rem Check if the file extension is png jpg or mp4 if /I "!ext!" == ".png" ( rem If the file extension is png jpg or mp4 copy the file and display a message rem echo Copying "%%f" to "%dst%\!relPath!" xcopy /y "%%f" "%dst%\!relPath!*" )else if /I "!ext!" == ".jpg" ( xcopy /y "%%f" "%dst%\!relPath!*" )else if /I "!ext!" == ".mp4" ( xcopy /y "%%f" "%dst%\!relPath!*" )else ( rem If the file extension is not png jpg or mp4, create a dummy file echo Creating dummy "%%f" to "%dst%\!relPath!" xcopy /y "%dummy%" "%dst%\!relPath!*" ) ) ) echo Done.
问题细节
问题出在提取相对路径的步骤:当文件名或子文件夹名包含!时,relPath变量会丢失!之后的所有内容(奇怪的是扩展名还能保留)。而且我担心就算能正确存储relPath,后续用"%dst%\!relPath!"做文件存在判断或复制操作时,还是会遇到同样的问题。
尝试与改进过程
后来我按照@harrymc的建议修改了脚本,在for循环内部新增了setlocal EnableExtensions EnableDelayedExpansion和endlocal,部分解决了感叹号的问题,但还是有一些文件名会报错(比如长路径或者含特殊符号的情况)。修改后的脚本如下:
@echo off setlocal EnableExtensions EnableDelayedExpansion rem Set the source and destination folders set "src=L:\folderS\sub1\sub2" set "dst=L:\folderD\sub1" rem Set the path to the dummy file that we need to create dummy files with xcopy set "dummy=L:\dummy.txt" rem Create the destination folder if it doesn't exist if not exist "%dst%" mkdir "%dst%" rem Loop through all the files in the source folder for /R "%src%" %%f in (*) do ( rem Get the file path set "filePath=%%f" echo the full path is !filePath! rem Get the file extension set "ext=%%~xf" setlocal EnableExtensions EnableDelayedExpansion rem Get the relative path excluding the path until the specified src folder set "relPath=!filePath:%src%\=!" echo the relative path is !relPath! rem Check if the file does not exist in the destination if not exist "%dst%\!relPath!" ( rem Check if the file extension is png jpg or mp4 if /I "!ext!" == ".png" ( rem If the file extension is png jpg or mp4 copy the file and display a message rem echo Copying "%%f" to "%dst%\!relPath!" xcopy /y "%%f" "%dst%\!relPath!*" )else if /I "!ext!" == ".jpg" ( xcopy /y "%%f" "%dst%\!relPath!*" )else if /I "!ext!" == ".mp4" ( xcopy /y "%%f" "%dst%\!relPath!*" )else ( rem If the file extension is not png jpg or mp4, create a dummy file echo Creating dummy "%%f" to "%dst%\!relPath!" xcopy /y "%dummy%" "%dst%\!relPath!*" ) ) endlocal ) echo Done.
最终解决方法
最后发现问题出在xcopy的调用参数上,原来的xcopy /y "%%f" "%dst%\!relPath!*"需要改成:
echo F|xcopy "!filePath!" "%dst%\!relPath!"
这个修改不仅解决了特殊符号的问题,echo F|还能自动回答xcopy的“文件/目录”询问,不用手动干预。
目前xcopy还有个潜在的256字符路径长度限制,不过我暂时没碰到这个情况;如果要彻底解决路径长度问题可以换用robocopy,但它的参数逻辑和xcopy差异较大,我暂时就先用这个方案了。
备注:内容来源于stack exchange,提问作者diegopau
相关产品推荐
相关产品推荐

