如何在不使用*.bat扩展名的情况下运行批处理脚本

34

在Windows中,是否有一种方法可以执行没有*.bat扩展名的批处理脚本?


4
好的,你可以将其重命名为.cmd文件... - Greg Hewgill
3
脚本必须有扩展名(.BAT或.CMD),以便让Windows知道它是一个批处理脚本。我认为不可能定义自己的扩展名来表示批处理文件,也不可能在使用时指定任何文件作为批处理脚本。 - dbenham
@dbenham 不好意思,兄弟,我还没有测试过,我是通过手机回复的。但我相信我之前见过 .batch 扩展名。但我谷歌了一下,发现我错了。感谢你纠正我。 - Mukul Goel
这个问题的触发原因是什么? - Bill_Stewart
7个回答

23

这对我来说是一个有趣的话题!我想对它进行一些观察。

首先要明确的是:批处理文件是具有 .BAT 或 .CMD 扩展名的文件。批处理文件除了执行通常的 DOS 命令外,还可以实现特定的批处理文件功能,尤其包括:

  • 通过 %1 %2 ... 访问批处理文件参数,并执行 SHIFT 命令。
  • 执行 GOTO 命令。
  • 执行 CALL :NAME 命令(内部子程序)。
  • 执行 SETLOCAL/ENDLOCAL 命令。

现在来说有趣的部分:任何文件都可以被重定向为 CMD.exe 的输入,因此其中包含的 DOS 命令会以类似于批处理文件的方式执行,但存在一些差异。最重要的差异在于之前提到的批处理文件功能将不起作用。另外一些差异在下面的非批处理文件中进行了说明(我称其为 BATCH.TXT):

@echo off
rem Echo off just suppress echoing of the prompt and each loop of FOR command
rem but it does NOT suppress the listing of these commands!

rem Pause command does NOT pause, because it takes the character that follows it
pause
X

rem This behavior allows to put data for a SET /P command after it
set /P var=Enter data: 
This is the data for previous command!
echo Data read: "%var%"

rem Complex FOR/IF commands may be assembled and they execute in the usual way:
for /L %i in (1,1,5) do (
   set /P line=
   if "!line:~0,6!" equ "SHOW: " echo Line read: !line:~6!
)
NOSHOW: First line read
SHOW: Second line
NOSHOW: This is third line
SHOW: The line number 4
NOSHOW: Final line, number five

rem You may suppress the tracing of the execution redirecting CMD output to NUL
rem In this case, redirect output to STDERR to display messages in the screen
echo This is a message redirected to STDERR >&2

rem GOTO command doesn't work:
goto label
goto :EOF
rem but both EXIT and EXIT /B commands works:
exit /B

:label
echo Never reach this point...

要执行前一个文件,请输入:CMD /V:ON < BATCH.TXT 需要使用/V开关以启用延迟扩展。
更专业的差异与NOT-Batch文件中的命令在命令行上下文中执行有关,而不是在Batch文件上下文中执行。也许Dave或jeb可以详细说明这一点。
编辑:附加观察结果(batch2.txt):
@echo off
rem You may force SET /P command to read the line from keyboard instead of
rem from following lines by redirecting its input to CON device.

rem You may also use CON device to force commands output to console (screen),
rem this is easier to write and read than >&2

echo Standard input/output operations> CON
echo/> CON
< CON set /P var=Enter value: > CON
echo/> CON
echo The value read is: "%var%"> CON

这样执行上一个文件:CMD < BATCH2.TXT > NUL

编辑: 更多的附加观察 (batch3.txt)

@echo off

rem Dynamic access to variables that usually requires DelayedExpansion via "call" trick

rem Read the next four lines; "next" means placed after the FOR command
rem (this may be used to simulate a Unix "here doc")

for /L %i in (1,1,4) do (
   set /P line[%i]=
)
Line one of immediate data
This is second line
The third one
And the fourth and last one...

(
echo Show the elements of the array read:
echo/
for /L %i in (1,1,4) do call echo Line %i- %line[%i]%
) > CON

按照通常的方式执行此文件:CMD < BATCH3.TXT > NUL

有趣!不是吗?

编辑:现在,在NotBatch.txt文件中可以模拟GOTO和CALL命令!!!请参见此帖子

安东尼奥


是的,有趣但 - 唉! - 繁琐。 - Henrik4

9

只需使用:

type mybat.txt | cmd

将其拆分...

type mybat.txt 读取 mybat.txt 的文本文件并打印内容。 | 表示捕获命令左侧的所有输出并将其传递给右侧的命令作为输入。然后 cmd(您可能已经猜到了)将接收到的任何输入解释为命令并执行它们。

如果您想知道... 您可以将 cmd 替换为 bash 并在 Linux 上运行。


2
在我的情况下,为了使Windows运行没有扩展名的文件(仅限于*.cmd、*.exe),我发现我错过了系统变量中的pathext变量以包含.cmd。一旦添加了这个变量,我就不再需要运行file.cmd,只需要运行file即可。
环境变量--> 添加/编辑系统变量以包括.cmd;.exe(当然你的文件应该在路径中)。

0

这可能是可能的,但可能不是一件容易的事情 =) 因为首先..安全性。 我曾经尝试过做同样的事情,几年前和几个月前,但是我没有找到解决方案..你可以尝试去做

execu.cmd

type toLaunch.txt >> bin.cmd
call bin.cmd
pause > nul
exit

然后在 toLaunch.txt 文件中放置

@echo off
echo Hello!
pause > nul
exit

举个例子,它会“编译”代码,然后执行“输出”文件,这只是“解析”

你也可以使用其他名称而不是解析,并在脚本中使用toLaunch.txt来自动重命名

ren %0 %0.txt

希望有所帮助!


0

这在某种程度上是可能的。您需要具有管理员权限才能运行 assocftype 命令。还需要一个“调用者”脚本来使用您的代码:

假设您想要的扩展名为 .scr。 然后以管理员身份执行此脚本:

   @echo off
   :: requires Admin permissions
   :: allows a files with .scr (in this case ) extension to act like .bat/.cmd files.
   :: Will create a 'caller.bat' associated with the extension
   :: which will create a temp .bat file on each call (you can consider this as cheating)
   :: and will call it.
   :: Have on mind that the %0 argument will be lost.


    rem :: "installing" a caller.
    if not exist "c:\scrCaller.bat" (
       echo @echo off
       echo copy "%%~nx1"  "%%temp%%\%%~nx1.bat" /Y ^>nul
       echo "%%temp%%\%%~nx1.bat"  %%*
    ) > c:\scrCaller.bat

    rem :: associating file extension
    assoc .scr=scrfile
    ftype scrfile=c:\scrCaller "%%1" %%*

你甚至可以使用GOTO、CALL和其他你知道的技巧。唯一的限制是%0参数将会丢失,但在创建临时文件时可以硬编码。

由于很多语言都会编译成.exe文件,我认为这是一个合法的方法。


0

原帖中没有描述任何原因或工作流程。但是,如果您只想键入myscript而不是myscript.bat,则可以创建脚本的别名并将别名重命名为myscript

我的用例:我在wsl和批处理shell中并行工作,想要键入ls而不是dirmv而不是move。因此,我创建了一些单行脚本,例如 ls.bat,其中包含dir %1的内容,并创建链接ls


-2
如果您想将变量导出到调用批处理文件中,可以使用以下方法:
for /F "tokens=*" %%g in (file.txt) do (%%g)

这种方法有一些限制(不要使用::作为注释),但它非常适合配置文件。

例如:

rem Filename: "foo.conf"
rem 
set option1=true
set option2=false
set option3=true

@echo off
for /F "tokens=*" %%g in (foo.conf) do (%%g)
echo %option1%
echo %option2%
echo %option3%
pause

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接