Переменные в пакете ведут себя не так, как ожидалось

Я боролся за то, чтобы получить правильный синтаксис для этого командного файла, и я не могу понять, почему некоторые вещи не работают.

1) Переменная 'i' не увеличивается. и 2) Конкатенация на strc, похоже, не хочет... ну, конкатенация.

set i=0
set "strc=concat:"

for %%f in (*.mp4) do (
    set /a i+=1
    set "str=intermediate%i%.ts"

    set strc="%strc% %str%|"

    ffmpeg -i "%%f" -c copy -bsf:v h264_mp4toannexb -f mpegts "%str%"
)

set strc="%strc:-1%"
ffmpeg -i "%strc%" -c copy -bsf:a aac_adtstoasc Output.mp4

1 ответ

Решение

Вы не первый, кто попал в знаменитую "ловушку с отложенным расширением" (и вы не будете последним)

Вам нужно отложенное расширение, если вы хотите использовать переменную, которую вы изменили в одном и том же блоке (блок представляет собой последовательность команд в скобках ( а также ))

Задержанные переменные ссылаются с !var! вместо %var%

Причина - это путь, cmd разбирает код. Полная строка или блок анализируются сразу, заменяя нормальные переменные их значением во время анализа. Задержанные переменные оцениваются во время выполнения.

Две простые партии для демонстрации:

setlocal enabledelayedexpansion
set "var=hello"
if 1==1 (
  set "var=world"
  echo %var% !var!
)

,

setlocal enabledelayedexpansion
for /L %%i in (1,1,5) do (
  echo %random% !random!
)

Примечание: также строка рассматривается как блок:

set "var=old"
set "var=new" & echo %var% 

с задержкой расширения:

setlocal enabledelayedexpansion
set "var=old"
set "var=new" & echo !var! 

Задержка расширения по умолчанию отключена в командной строке. Если вам это действительно нужно, вы можете сделать:

cmd /v:on /c "set "var=hello" & echo !var!"

Также есть способ сделать то же самое без отложенного расширения (но call стоит некоторое время, поэтому это медленнее, но если по какой-то причине вы не можете / не хотите использовать отложенное расширение, это альтернатива):

setlocal DISabledelayedexpansion
for /L %%i in (1,1,5) do (
  call echo %random% %%random%% 
)

Оба метода также могут использоваться для отображения переменных, похожих на массивы:

(это часто спрашивают как "переменная, которая содержит другую переменную" или "вложенные переменные"
Вот коллекция для использования таких массивоподобных переменных в различных ситуациях:

с задержкой расширения:

setlocal ENabledelayedexpansion
set "num=4"
set "var[%num%]=HELLO"
echo plain delayed: !var[%num%]!
for /l %%i in (4,1,4) do (
  echo for delayed: !var[%%i]!
  set a=%%i
  call echo for delayed with variable: %%var[!a!]%%
)

без отложенного расширения:

setlocal DISabledelayedexpansion
set "num=4"
set "var[%num%]=HELLO"
call echo plain called: %%var[%num%]%%
for /l %%i in (4,1,4) do (
  call echo FOR called: %%var[%%i]%%
  set a=%%i
  call echo FOR called with variable: %%var[%a%]%%
)
Другие вопросы по тегам