Почему forfiles проглатывает первый аргумент команды?
Я пытаюсь сделать что-то похожее на Получить Visual Studio для запуска шаблона T4 для каждой сборки, используя cmd forfiles
, чтобы преобразовать каждый шаблон в VS2008.
Если я выполняю
forfiles /m "*.tt" /s /c "\"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
тогда я получаю сообщение об ошибке TextTransform.exe
(экран текста, объясняющий, как передать его в качестве аргументов).
Если я вместо этого выполняю
forfiles /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
тогда он отлично работает.
Чтобы отладить это, я создал простую программу командной строки под названием debugargs
, которая просто печатает количество аргументов, которые оно получает, и их значения. Затем некоторые эксперименты показывают, что первая форма прямого прохождения команды до forfiles
вызывает проглатывание первого аргумента. Например.
forfiles /m "*.tt" /s /c "debugargs.exe 1 2 3"
выводит вывод
2 arguments supplied
#1: 2
#2: 3
документация Я смог найти довольно редкий вариант, и я не вижу упоминания об этом как возможности. Это просто непонятная ошибка, или я чего-то не хватает?
Ответы
Ответ 1
Это кажется ошибкой в способе forfiles
вызывает .exe
s. В ожидании я расширил программу debugargs
, чтобы напечатать полную командную строку.
X:\MyProject>forfiles /m "*.tt" /s /c "debugargs.exe 1 2 @file"
2 arguments supplied
#1: 2
#2: Urls.tt
Full command line: 1 2 "Urls.tt"
Таким образом, наиболее подходящим решением будет удвоение исполняемого имени:
forfiles /m "*.tt" /s /c "debugargs.exe debugargs.exe 1 2 @file"
Альтернативным решением является вызов cmd /c
. Однако обратите внимание, что если вам нужно процитировать исполняемый путь (например, потому что он содержит пробел), вам потребуется дополнительное обходное решение для добавления @
:
forfiles /m "*.tt" /s /c "cmd /c @\"debugargs.exe\" 1 2 @file"
Ответ 2
Я воспроизвел и поведение в файлах. Вы можете обойтись, используя команду cmd/c перед командой, или вы можете перейти на PowerShell, где эквивалентная команда будет что-то вроде этого (не проверена):
get-childitem . -filter "*.tt" -recurse | foreach-object {
& "${ENV:CommonProgramFiles(x86)}\Microsoft Shared\TextTemplating\1.2\TextTransform.exe" "`"$($_.Name)`""
}
Билл
Ответ 3
Я тоже борется с этим. Обход, который я нашел, - это просто добавить дополнительное пространство между командой и первым аргументом! Итак, где я пытался:
FORFILES /s /m *.dll /c "python \"c:\path\to\script.py\" -t arg1 etc"
python пытался найти файл "arg1" для выполнения, но если я просто изменил его на:
FORFILES /s /m *.dll /c "python \"c:\path\to\script.py\" -t arg1 etc"
это действительно работает!