Shell script и его Windows эквивалент

лет ми тэлл зэ хоррор стори
жил был шелл скрипт

PCLASSPATH=.
for i in `ls lib/*.jar`
do
PCLASSPATH=${PCLASSPATH}:${i}
done
java -cp $PCLASSPATH blablabla

и понадобилось сделать его виндовс-эквивалент
в первом приближении, родилось шо-то такое:

set PCLASSPATH=.
FOR %%I IN (1 2 3) DO ECHO set PCLASSPATH="%PCLASSPATH%;%%I"
ECHO %PCLASSPATH%
java -cp %PCLASSPATH% blablabla

первый сюрприз - это требование использовать %%I при исполнении из файла, %I - если выполнять из командной строки

у меня недостаточно бурное воображение, чтобы придумать причину, почему этот дибилизм с разной семантикой в файле и командной строке вообще можно было получить, не смотря уже про вывод в доку как фичи :)

но это всё херня
потому шо какбе внезапно после выполнения этого скриптика, в итоге в %PCLASSPATH% оказывалось значение ".;3" вместо ожидаемого ".;1;2;3"

думаю такой, шозанах?! оно выполняло каждую итерацию, используя исходное значение переменной PCLASSPATH, не перезаписывая его

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

карочи

думаю ладно, не хочешь переписывать значение переменной, будем писать в файл, собирать там
потом как-то оттуда собранный список вытаскивать обратно в переменную
в итоге, пришел к такому:

FOR /F "usebackq" %%I IN (`dir lib /B`) DO ECHO ;%%I >> output

/F "usebackq" нужно было шоб оно стало понимать обратные кавычки
интересно, откуда они спиздили оборачивание команды в обратные кавычки? :)
ну то такое
далее
поимел файл вида:
.
;aopalliance-1.0.jar
;asm-3.3.jar
;avalon-framework-4.1.3.jar
;commons-cli-1.2.jar
;commons-logging-1.1.jar
... и так далее
теперь надо развернуть его в одну строку и запихнуть в переменную окружения
ок думаю, пошел делать set /?
там оказалось многа букав, в том числе пара абзацев, которые я перечитывал раза три, не веря своим глазам:
Связывание времени выполнения для переменных среды окружения полезно при обходе ограничений раннего связывания, которое происходит при первом чтении текстовой строки, а не при ее выполнении. Следующий пример демонстрирует возникающую проблему при использовании раннего связывания переменных:

set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo Тело внутреннего оператора сравнения
)

Данное сообщение не будет выводиться, т.к. %VAR% в ОБОИХ выражениях IF подставляется в момент первого использования в первом IF, в том числе и в тело первого ветвления IF, которое является составным выражением. В IF внутри составного выражения в действительности сравниваются значения "before" и "after", что заведомо ложно. Следующий пример демонстрирует подобную ошибку:

set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%

в данном случае список файлов текущей папки никогда не будет построен. Вместо этого, значением переменной LIST будет имя последнего найденного файла. И вновь, это случилось потому, что %LIST% подставляется всего один раз - в момент обработки выражения FOR, когда список еще пуст. Фактически, приведенный фрагмент эквивалентен следующему примеру:

for %i in (*) do set LIST= %i

в котором имя последнего найденного файла сохраняется в переменной LIST.

ЭТО ЖЕ ЭПИЧЕСКИЙ ПИЗДЕЦ
вопрос ставится так, типа "вот, нормальный код - это заведомо ложная неверно ошибочно сформулированная лабуда"
и типа "у нас мозг работает на бейсике, поэтому конечно же, там должно быть тока последнее значение"
СУКИ! Какого хера это написано в хелпе для команды SET а не FOR??!! АААААаааа
Не, я всё понимаю, гугл наверно показал бы мне какое-то решение этой проблемы, но вот че-то мне как бы посмотреть на то шо я могу поиметь не имеея гугла и других наработок, типа а-ля с нуля, руководствуясь только документацией и здравым смыслом, простите за неприличные слова.

НО! Дальше - файнее. Имеем еще кусочек счастья:
Связывание времени выполнения для переменных среды окружения происходит при
использовании специального символа (восклицательного знака), обозначающего
проведение сопоставления во время выполнения. Если включена поддержка
связывания времени выполнения, то для достижения ожидаемых результатов
приведенные выше фрагменты должны быть изменены следующим образом:

set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo Тело внутреннего оператора сравнения
)

set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%

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

ААААааааа, вот оно, счастье, надо всего-то пользовать !восклицательные знаки! вместо %процентов%
Вот только "если включена поддержка связывания времени выполнения", а как её включить?
ну, гугл в помасч, ага
этот режим включается параметром к командному интерпретатору, надо запускать CMD.EXE /V:ON
фсё блин, гайки! уже никакой прозрачности и аут-оф-бокс рэди, пиши теперь ридми отдельный с этим спешл реквайрмент
кстати, хелп для CMD тоже доставляет:

/V:ON
Разрешение отложенного расширения переменных среды с применением символа '!' в качестве разделителя. Например, /V:ON разрешает использовать !var! в качестве расширения переменной var во время выполнения. Синтаксис var служит для расширения переменных при вводе, что приводит к совсем другим результатам внутри цикла FOR.

/V:OFF
Запрет отложенного расширения переменных среды.

ААААаааа, "приводит к совсем другим результатам" !!
Осторожно! Оно внезапно начнёт работать как положено, все скрипты поламаются!
Так вот, оно ВНЕЗАПНО не стало работать как положенно, и с в CMD /V:ON скрипт выполнялся так же как и без него
на этом этапе мне надоело
Сделаю генератор скрипта который при мавен-билде будет рисовать цээмдешник без форов и прочих микропотуг