2016-08-03 123 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%\??.?.*"(「兩個字符,點,一個字符,點,無論」)