В пакетном файле, запущенном из Windows, выберите последнюю версию приложения, используя имя каталога
Я использую портативное приложение, которое имеет обновления довольно часто. Проблема в том, что в каждой версии приложения есть папка с именем "processing-xyz". Каждый раз, когда я устанавливаю новую версию, мне нужно связать файлы с новой версией, которая находится в другой папке. Чтобы обойти эту неприятность, я хочу связать тип файла "*.pde" с командным файлом.
Имена папок идут следующим образом
- Обработка-3.2.1
- Обработка-3.2.2
- и т.п.
Я создал этот небольшой пакетный скрипт, который получает исполняемый файл из последней версии.
@echo off
for /f "delims=" %%D in ('dir processing* /a:d /b /o-n') do (
set currentFolder=%%~fD
:: Check if environment variable already set
if not %currentFolder%==%processing% (
:: Set environment variable processing
setx processing %currentFolder%
)
%currentFolder%/processing.exe %1
goto :eof
)
Он работает при запуске из командной строки, но не в Windows. Есть ли конкретная причина? Кроме того, есть ли способ оптимизировать этот код?
Спасибо
3 ответа
Предположим, что номера версий всегда состоят из одной цифры, я бы сделал это следующим образом:
@echo off
rem // Reset variable:
set "currentFolder="
rem /* Loop through the folders in ascending order, overwrite the variable
rem in each iteration, so it holds the highest version finally: */
for /f "delims=" %%D in ('dir /B /A:D /O:N "processing-*.*.*"') do (
set "currentFolder=%%~fD"
)
rem // Check if environment variable is already set:
if not "%processing%"=="%currentFolder%" (
rem // Set environment variable `processing`:
setx processing "%currentFolder%"
)
rem // Execute `processing.exe`:
"%currentFolder%/processing.exe" "%~1"
Если отдельные номера версий могут состоять из более чем одной цифры (максимум четыре здесь), используйте это:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem /* Assign each found folder to a variable called `$ARRAY_X_Y_Z`, where `X`, `Y`, `Z`
rem are zero-padded variants of the original numbers `x`, `y`, `z`, so for instance,
rem a folder called `processing-4.7.12` is stored in variable `$ARRAY_0004_0007_0012`: */
for /F "tokens=1-4 delims=-. eol=." %%A in ('
dir /B /A:D "processing-*.*.*" ^| ^
findstr /R /I "^processing-[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*$"
') do (
rem // Perform the left-side zero-padding here:
set "MAJ=0000%%B" & set "MIN=0000%%C" & set "REV=0000%%D"
set "$ARRAY_!MAJ:~-4!_!MIN:~-4!_!REV:~-4!=%%A-%%B.%%C.%%D"
)
rem // Reset variable:
set "currentFolder="
rem /* Loop through the output of `set "$ARRAY_"`, which returns all variables beginning
rem with `$ARRAY_` in ascending alphabetic order; because of the zero-padding, where
rem alphabetic and alpha-numeric orders become equivalent, the item with the greatest
rem version number item is iterated lastly, therefore the latest version is returned: */
for /F "tokens=1,* delims==" %%E in ('set "$ARRAY_"') do (
set "currentFolder=%%F"
)
endlocal & set "currentFolder=%currentFolder%"
rem // The rest of the script os the same as above...
Вы также можете найти похожие подходы здесь:
- Как получить номер последней версии с помощью пакета (этот подход также основан на функции сортировки
set
команда) - Как отсортировать строки текстового файла с номерами версий в формате major.minor.build.revision numeric? (это использует
sort
команда на временном файле или на канале (|
) данные)
Не проверено (отредактировано: должно обрабатывать случаи, когда младшие версии имеют больше цифр):
@echo off
setlocal enableDelayedExpansion
set /a latest_n1=0
set /a latest_n2=0
set /a latest_n3=0
for /f "tokens=2,3* delims=-." %%a in ('dir processing* /a:d /b /o-n') do (
set "current_v=%%a.%%b.%%c"
set /a "current_n1=%%a"
set /a "current_n2=%%b"
set /a "current_n3=%%c"
if !current_n1! GTR !latest_n1! (
set /a latest_n1=!current_n1!
set /a latest_n2=!current_n2!
set /a latest_n3=!current_n3!
set "latest_v=!current_v!"
) else if !current_n1! EQU !latest_n1! if !current_n2! GTR !latest_n2! (
set /a latest_n1=!current_n1!
set /a latest_n2=!current_n2!
set /a latest_n3=!current_n3!
set "latest_v=!current_v!"
) else if !current_n1! EQU !latest_n1! if !current_n2! EQU !latest_n2! if !current_n3! GTR !latest_n3! (
set /a latest_n1=!current_n1!
set /a latest_n2=!current_n2!
set /a latest_n3=!current_n3!
set "latest_v=!current_v!"
)
)
echo latest version=processing-%latest_v%
@echo off
for /f "delims=" %%D in ('dir processing* /a:d /b /o-n') do (
if "%processing%" neq "%cd%\%%F" setx processing "%cd%\%%F" >nul
.\%%F\processing.exe %1
goto :eof
)
эквивалентный код - почти.
Первая проблема - ::
Форма комментариев не должна использоваться в блоке кода (заключенная в скобки серия операторов), так как ::
на самом деле это метка, которая сама по себе звездочка с двоеточием. Поскольку это метка, она завершает блок.
Следующая проблема - внутри блока кода, %var% refers to the value of
вар**as it stood when the
for` был обнаружен ** - не так, как он изменяется внутри цикла.
Следующая проблема - как отметили другие, /o-n
производит последовательность по имени, так 10
скорее всего отсортировать после 9
(так как сортировка обратная). Я не изменил это в коде замены, но /o-d
сортировка по обратной дате может лучше подходить для вашего приложения.
Теперь о том, как работает ваш код.
Первый, processing
устанавливается на любой установленный последний запуск. Если это отличается от значения, рассчитанного из этого прогона, то setx
новое значение. Причудливо, setx
не set
значение в текущем cmd
экземпляр, только для экземпляров, созданных в будущем.
Затем вы пытаетесь выполнить свой процесс и затем выходите из пакета с goto :eof
, Единственная проблема в том, что %currentfolder%
это не значение, измененное циклом, потому что оно должно быть в блоке кода. Похоже, что изменится ::-comments
сломали блок и где currentfolder
используется в вашем коде, он находится за пределами блока.
Вместо этого используйте .\%%F\executablename
что означает "из текущего имени каталога (.
); Подкаталог %%F
;filenametoexecute" - обратите внимание, что"\"является разделителем каталогов в окнах, '/' указывает на переключатель.