在Windows NMAKE的Makefile中获取最新创建的.yak文件
我有一个将由Windows NMAKE工具运行的Makefile:
push: cd dist "C:\Program Files\Rhino 7\System\Yak.exe" push myapp-*.yak
上述语句会抛出致命错误,因为Yak.exe工具需要文件的完整路径/名称。
dist子文件夹中包含如下文件:
myapp-1.2.0-rh7_13-win.yakmyapp-1.3.0-rh7_13-win.yakmyapp-1.4.0-rh7_13-win.yak- ...
如何以编程方式获取最新创建文件的完整名称?我希望能在Makefile中实现一个简单的Windows批处理脚本。
可选方案
我尝试了一些方案,但不知道如何实际实现。至少有两种方法可以确定最新创建的文件:
- 匹配
myapp-L.M.N-*-win.yak模式中版本号L、M、N最大的文件 - 根据文件时间戳判断
- 其他方法?
在帮助下,我实现了以下方案:
push: cd dist for /f "delims=" %%i in ('dir /b /od /a-d myapp-*-win.yak') do set LAST=%%i "C:\Program Files\Rhino 7\System\Yak.exe" push "%LAST%"
方向是对的,但存在问题:%LAST%变量无法从for循环正确传递到push语句中,我不确定如何正确传递该变量。使用do set "LAST=%%i"也会遇到同样的问题。
问题根源在于NMAKE会为每条缩进的命令启动单独的CMD进程,所以for循环中设置的LAST变量只在当前进程有效,下一条命令的进程无法读取到这个变量。
解决这个问题有两种简单可行的方式:
方式一:将所有命令合并到同一行(推荐)
把cd、for和push命令用&连接,让它们在同一个CMD进程中执行,直接在循环块内完成推送操作:
push: cd dist && for /f "delims=" %%i in ('dir /b /od /a-d myapp-*-win.yak') do "C:\Program Files\Rhino 7\System\Yak.exe" push "%%i"
dir /b /od /a-d参数说明:
/b:仅输出文件名,不显示额外信息/od:按文件创建时间从旧到新排序,循环最后一次赋值的%%i就是最新文件/a-d:排除目录,只处理文件
方式二:启用延迟变量扩展并合并命令块
如果需要保留变量的使用形式,可以启用CMD的延迟变量扩展,用括号包裹命令块确保在同一进程执行:
push: cd dist && (setlocal enabledelayedexpansion && for /f "delims=" %%i in ('dir /b /od /a-d myapp-*-win.yak') do set LAST=%%i && "C:\Program Files\Rhino 7\System\Yak.exe" push "!LAST!")
这里用!LAST!代替%LAST%,因为延迟变量扩展模式下需要用感叹号访问变量,setlocal enabledelayedexpansion用来开启该功能。
按版本号排序的替代方案
如果想通过版本号而非时间戳获取最新版本,可利用sort命令反向排序版本文件名,取第一行结果:
push: cd dist && for /f "delims=" %%i in ('dir /b /a-d myapp-*-win.yak ^| sort /r') do "C:\Program Files\Rhino 7\System\Yak.exe" push "%%i" & exit /b
sort /r实现反向排序,最新版本会排在第一行,exit /b确保循环只执行一次,直接取第一个结果。
内容的提问来源于stack exchange,提问作者Megidd

