2016-08-03 92 views
1

获得最新的版本号我有一个包含多个子目录如何使用批处理

Directories example

版本格式为[major].[minor].[update][phase][build],像1.0.0d0一个文件夹。有效的相位是d(ev),a(lpha),b(eta),f(inal),请注意d < a < b < f。

我想使用批处理脚本获取最新版本号16.0.0a2。我编写这样的代码,但不起作用,因为子目录按字母顺序排序。所以它会给出结果16.0.0d24。

SET BASEPATH=..... 
SET TEMPFILE=%TEMP%\%~n0%RANDOM% 
echo get latest export. 
DIR /A:D /B /ON "%BASEPATH%" > "%TEMPFILE%" 
FOR /F "usebackq delims=;" %%I IN ("%TEMPFILE%") DO (SET LATEST_VERSION=%%I) 
echo LATEST_VERSION 
+2

检查让你的版本文件夹,如果你能依靠'DIR/OD/TC '(按创建日期排序) – Stephan

+0

相关:[如何对包含版本号的文本文件的行进行排序,格式为major.minor.build.revision numerical?](http:// stackoverflow。com/q/34417346) – aschipfl

+0

是的,按创建时间排序也是一种方法。 –

回答

2

下面的脚本你想要做什么:

@echo off 
setlocal EnableExtensions EnableDelayedExpansion 

set "LOC=%~1" 
if not defined LOC set "LOC=." 
set /A "PADV=100, PADB=10000" 
set "SRCH=d" & set "[email protected]" 

for /F "tokens=1,2,* delims=." %%A in (' 
    dir /B /A:D /O:D /T:C "%LOC%" ^|^
     findstr /I /R "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[dabf][0-9][0-9]*" 
') do (
    set /A "MAJOR=%%A+PADV, MINOR=%%B+PADV" 
    for /F "tokens=1,* delims=DdAaBbFf" %%E in ("%%C") do (
     set /A "FIX=%%E+PADV, BUILD=%%F+PADB" 
     set "PHASE=%%C" & set "PHASE=!PHASE:*%%E=!" & set "PHASE=!PHASE:~,1!" 
     set "PHASE=!PHASE:%SRCH%=%REPL%!" 
    ) 
    set "VERSION[!MAJOR!.!MINOR!.!FIX!!PHASE!!BUILD!]=%%A.%%B.%%C" 
) 

for /F "tokens=2 delims==" %%V in ('2^> nul set VERSION[') do (
    set "LATEST=%%V" 
    echo(%%V 
) 
if defined LATEST echo Latest: & echo(%LATEST% 

endlocal 
exit /B 

的基本概念是使(α-)数字排序提供了相同的结果字母排序相适应的版本号。这可以通过在版本号的每个数字部分添加一个很大的数字来实现,这样每个数字部分的数字总是相同的。此外,由于阶段图的优先级不是按字母顺序排列的,因此可以进行适当的替换。

核心思想取自this answer并记入Aacini

+0

我想知道为什么人们不会使用像Python这样的更强大的语言来做类似的事情。我明白批处理文件是一个引导程序来安装一些更强大的东西,但这不是这种情况。但是:印象深刻的答案 –

+0

@ Jean-FrançoisFabre,我想这个任务也可以很容易地通过PowerShell来完成,这是Windows原生的,但OP没有相应地标记问题...... – aschipfl

0

只是为了笑,oneliner在python中就是这样。不需要upvote(或downvote :))。

黑客将字母视为十六进制值,并将d转换为9来尊重OP请求。另一个困难是数字排序(对于字母排序来说这很容易)。我认为这会更简单,但并不那么简单。

一条线(版本在versort目录)

import os,re; print(sorted(os.listdir(os.path.join(basepath,"versort")),reverse=True,key=lambda i: list(map(lambda x:int(x,16),re.sub("([a-z])",r".\1.",i).replace("d","9").split("."))))[0]) 
+0

只是另一个笑声; [my batch-oneliner](http://stackoverflow.com/a/38742562/2152082)比你短':D' – Stephan

+0

@Stephan:这是作弊,但很好 –

1

类似代码到由aschipfl所述一个posted。每个段的值填充方法相同,只是名称拆分和值填充的​​不同处理。

@echo off 
    setlocal enableextensions disabledelayedexpansion 

    rem Give a path as argument or use current active directory 
    for %%a in ("%~f1.") do set "target=%%~fa" 

    rem Prepare variables to handle phase order correction and 
    rem storage of intermediate/final values 
    set /a "_d=0", "_a=1", "_b=2", "_f=3" 
    set "lastValue=" 
    set "lastVersion=" 

    rem %%a : Search the folders and split their name using dot as delimiter 
    rem  %%a = major 
    rem  %%b = minor 
    rem  %%c = update + phase + build 
    rem %%d : split %%c using [dabf] as delimters to obtain 
    rem  %%d = update 
    rem  %%e = build 
    rem %%f : split %%c using numbers as delimiters to obtain 
    rem  %%f = phase 
    set "num=[0-9][0-9]*" 
    for /f "tokens=1-3 delims=." %%a in (' 
     dir /b /ad /o-d "%target%" 
     ^| findstr /r /i /x /c:"%num%\.%num%\.%num%[dabf]%num%" 
    ') do for /f "tokens=1,2 delims=dDaAbBfF" %%d in ("%%c" 
    ) do for /f "delims=" %%f in ("%%c" 
    ) do (
     rem Folder name has been splitted. Now, convert each of the segments 
     rem to a numerical value, adding 1E6 to get a proper padding as all 
     rem values will be handled as strings to avoid limits in batch 
     rem arithmetic for values over 2^31 
     rem Note that %%f is not being iterated here as the values to use 
     rem for phase padding have been previously defined 
     for %%v in (
      %%a %%b %%d %%e 
     ) do if not defined _%%v set /a "_%%v=1000000 + %%v" 

     rem Obtain the properly padded version of the folder segments 
     setlocal enabledelayedexpansion 
     for /f "tokens=1,2" %%i in (
      "!_%%a!!_%%b!!_%%d!!_%%f!!_%%e! !lastValue!" 
     ) do (
      endlocal 
      rem Determine if we have found a newer version 
      if "%%i" gtr "%%j" (
       set "lastValue=%%i" 
       set "lastVersion=%%a.%%b.%%c" 
      ) 
     ) 
    ) 

    if defined lastVersion (
     echo Latest version found is : %lastVersion% 
    ) else (
     echo No matching folders 
    ) 
1

创建日期应该是一个很好的绕圈在这种情况下,排序:

... 
echo get latest export. 
FOR /F "delims=" %%I IN ('DIR /AD /B /OD /TC "%BASEPATH%"') DO SET "LATEST_VERSION=%%I" 
echo %LATEST_VERSION% 

dirα参数:
/OD按日期/时间
/TC挑创建日期(而不是默认“最后修改日期”)
/AD只显示目录
/B只显示名称,没有标题,没有大小,日期等,没有总结。

如果有最大是其他文件夹也与dir ... "%basedir%\??.?.*"(“两个字符,点,一个字符,点,无论”)