问题描述
在 Microsoft Windows 7
中,我在 C:\new
目录中有两个 Kotlin 源代码:
- hello1.kt
- hello2.kt
我可以在命令行中单独编译它们,其当前工作目录是C:\
,例如>kotlinc hello1.kt
。但是当我尝试进行批处理编译时,出现错误:
C:\new>kotlinc *.kt
error: source file or directory not found: *.kt
注意事项:
-
kotlinc .\*.kt
的结果是一样的。 -
> dir *.kt
正确列出了.kt
个文件,因此问题不可能出在大约*
通配符中。 -
$ kotlinc *.kt
在Linux
中正常工作,没有错误。
我想知道是什么导致了问题?有没有办法在 Microsoft Windows
中进行批量编译?
解决方法
看起来 kotlinc.exe
不支持通配符模式作为参数。所以必须在 Windows 上使用 kotlinc hello1.kt hello2.kt
。
Linux/Mac 上的 shell 解释器在执行可执行文件之前将诸如 *.kt
之类的通配符模式扩展为具有匹配文件/文件夹名称的参数字符串列表。因此,Linux/Mac 上的 shell 解释器不会使用 kotlinc
调用 *.kt
,而是使用 hello1.kt hello2.kt
调用可执行文件。
Windows 命令处理器 cmd.exe
在可执行文件的参数列表中不提供这种通配符扩展。可执行文件本身必须支持带有通配符模式的参数,并自行搜索匹配的文件/文件夹。
Windows 批处理文件解决方案将遵循适用于除带感叹号的文件名之外的所有文件名的代码:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Make the directory of the batch file the current directory.
pushd "%~dp0" || goto :EOF
if exist *.kt goto CreateFilesList
echo ERROR: There is no *.kt file in folder: "%~dp0"
echo/
pause
goto EndBatch
:CreateFilesList
set "FilesList="
for %%I in (*.kt) do set FilesList=!FilesList! "%%I"
rem The files list starts with a space character.
kotlinc.exe!FilesList!
if errorlevel 1 echo/& pause
:EndBatch
rem Restore the initial current directory.
popd
endlocal
一种较慢的解决方案,也适用于文件名中有一个或多个 .kt
的 !
文件名。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Make the directory of the batch file the current directory.
pushd "%~dp0" || goto :EOF
if exist *.kt goto CreateFilesList
echo ERROR: There is no *.kt file in folder: "%~dp0"
echo/
pause
goto EndBatch
:CreateFilesList
set "FilesList="
for %%I in (*.kt) do call :AddToList "%%I"
goto RunKotlinC
:AddToList
set FilesList=%FilesList% %1
goto :EOF
:RunKotlinC
rem The files list starts with a space character.
kotlinc.exe%FilesList%
if errorlevel 1 echo/& pause
:EndBatch
rem Restore the initial current directory.
popd
endlocal
请注意,文件名列表不是无限的。环境变量定义的最大长度为 8192 个字符,其中包括变量名称、等号、分配给环境变量的字符串值和终止空字节。添加到列表中的文件名没有路径。因此,只要一次执行 .kt
不应该编译数百个 kotlinc.exe
文件,这个限制在这里应该没有问题。
要了解使用的命令及其工作原理,请打开 command prompt 窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
popd /?
pushd /?
rem /?
set /?
setlocal /?
另见: